1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2023 Realtek Corporation 3 */ 4 5 #include "chan.h" 6 #include "debug.h" 7 #include "mac.h" 8 #include "phy.h" 9 #include "reg.h" 10 #include "rtw8922a.h" 11 #include "rtw8922a_rfk.h" 12 13 static void rtw8922a_tssi_cont_en(struct rtw89_dev *rtwdev, bool en, 14 enum rtw89_rf_path path) 15 { 16 static const u32 tssi_trk_man[2] = {R_TSSI_PWR_P0, R_TSSI_PWR_P1}; 17 18 if (en) 19 rtw89_phy_write32_mask(rtwdev, tssi_trk_man[path], B_TSSI_CONT_EN, 0); 20 else 21 rtw89_phy_write32_mask(rtwdev, tssi_trk_man[path], B_TSSI_CONT_EN, 1); 22 } 23 24 void rtw8922a_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, u8 phy_idx) 25 { 26 if (rtwdev->mlo_dbcc_mode == MLO_1_PLUS_1_1RF) { 27 if (phy_idx == RTW89_PHY_0) 28 rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_A); 29 else 30 rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_B); 31 } else { 32 rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_A); 33 rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_B); 34 } 35 } 36 37 static 38 void rtw8922a_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, 39 const struct rtw89_chan *chan) 40 { 41 const u32 rf_addr[2] = {RR_CFGCH, RR_CFGCH_V1}; 42 struct rtw89_hal *hal = &rtwdev->hal; 43 u32 rf_reg[RF_PATH_NUM_8922A][2]; 44 u8 synpath; 45 u32 rf18; 46 u8 kpath; 47 u8 path; 48 u8 i; 49 50 rf_reg[RF_PATH_A][0] = rtw89_read_rf(rtwdev, RF_PATH_A, rf_addr[0], RFREG_MASK); 51 rf_reg[RF_PATH_A][1] = rtw89_read_rf(rtwdev, RF_PATH_A, rf_addr[1], RFREG_MASK); 52 rf_reg[RF_PATH_B][0] = rtw89_read_rf(rtwdev, RF_PATH_B, rf_addr[0], RFREG_MASK); 53 rf_reg[RF_PATH_B][1] = rtw89_read_rf(rtwdev, RF_PATH_B, rf_addr[1], RFREG_MASK); 54 55 kpath = rtw89_phy_get_kpath(rtwdev, phy); 56 synpath = rtw89_phy_get_syn_sel(rtwdev, phy); 57 58 rf18 = rtw89_read_rf(rtwdev, synpath, RR_CFGCH, RFREG_MASK); 59 if (rf18 == INV_RF_DATA) { 60 rtw89_warn(rtwdev, "[RFK] Invalid RF18 value\n"); 61 return; 62 } 63 64 for (path = 0; path < RF_PATH_NUM_8922A; path++) { 65 if (!(kpath & BIT(path))) 66 continue; 67 68 for (i = 0; i < 2; i++) { 69 if (rf_reg[path][i] == INV_RF_DATA) { 70 rtw89_warn(rtwdev, 71 "[RFK] Invalid RF_0x18 for Path-%d\n", path); 72 return; 73 } 74 75 rf_reg[path][i] &= ~(RR_CFGCH_BAND1 | RR_CFGCH_BW_V2 | 76 RR_CFGCH_BAND0 | RR_CFGCH_CH); 77 rf_reg[path][i] |= rtw89_chip_chan_to_rf18_val(rtwdev, chan); 78 79 rtw89_write_rf(rtwdev, path, rf_addr[i], 80 RFREG_MASK, rf_reg[path][i]); 81 fsleep(100); 82 } 83 } 84 85 if (hal->cv != CHIP_CAV) 86 return; 87 88 if (chan->band_type == RTW89_BAND_2G) { 89 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000); 90 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x00003); 91 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c990); 92 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0xebe38); 93 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x00000); 94 } else { 95 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000); 96 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x00003); 97 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c190); 98 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0xebe38); 99 rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x00000); 100 } 101 } 102 103 void rtw8922a_set_channel_rf(struct rtw89_dev *rtwdev, 104 const struct rtw89_chan *chan, 105 enum rtw89_phy_idx phy_idx) 106 { 107 rtw8922a_ctl_band_ch_bw(rtwdev, phy_idx, chan); 108 } 109 110 enum _rf_syn_pow { 111 RF_SYN_ON_OFF, 112 RF_SYN_OFF_ON, 113 RF_SYN_ALLON, 114 RF_SYN_ALLOFF, 115 }; 116 117 static void rtw8922a_set_syn01_cav(struct rtw89_dev *rtwdev, enum _rf_syn_pow syn) 118 { 119 if (syn == RF_SYN_ALLON) { 120 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3); 121 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x2); 122 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3); 123 124 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x3); 125 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x2); 126 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x3); 127 } else if (syn == RF_SYN_ON_OFF) { 128 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3); 129 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x2); 130 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3); 131 132 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x0); 133 } else if (syn == RF_SYN_OFF_ON) { 134 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x0); 135 136 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x3); 137 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x2); 138 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x3); 139 } else if (syn == RF_SYN_ALLOFF) { 140 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x0); 141 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x0); 142 } 143 } 144 145 static void rtw8922a_set_syn01_cbv(struct rtw89_dev *rtwdev, enum _rf_syn_pow syn) 146 { 147 if (syn == RF_SYN_ALLON) { 148 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN_V1, 0xf); 149 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN_V1, 0xf); 150 } else if (syn == RF_SYN_ON_OFF) { 151 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN_V1, 0xf); 152 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN_V1, 0x0); 153 } else if (syn == RF_SYN_OFF_ON) { 154 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN_V1, 0x0); 155 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN_V1, 0xf); 156 } else if (syn == RF_SYN_ALLOFF) { 157 rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN_V1, 0x0); 158 rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN_V1, 0x0); 159 } 160 } 161 162 static void rtw8922a_set_syn01(struct rtw89_dev *rtwdev, enum _rf_syn_pow syn) 163 { 164 struct rtw89_hal *hal = &rtwdev->hal; 165 166 rtw89_debug(rtwdev, RTW89_DBG_RFK, "SYN config=%d\n", syn); 167 168 if (hal->cv == CHIP_CAV) 169 rtw8922a_set_syn01_cav(rtwdev, syn); 170 else 171 rtw8922a_set_syn01_cbv(rtwdev, syn); 172 } 173 174 static void rtw8922a_chlk_ktbl_sel(struct rtw89_dev *rtwdev, u8 kpath, u8 idx) 175 { 176 u32 tmp; 177 178 if (idx > 2) { 179 rtw89_warn(rtwdev, "[DBCC][ERROR]indx is out of limit!! index(%d)", idx); 180 return; 181 } 182 183 if (kpath & RF_A) { 184 rtw89_phy_write32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_EN, 0x1); 185 rtw89_phy_write32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_IQC_V1, idx); 186 rtw89_phy_write32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_MDPD_V1, idx); 187 rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT, RR_TXG_SEL, 0x4 | idx); 188 189 tmp = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL, BIT(0)); 190 rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, tmp); 191 tmp = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL, BIT(1)); 192 rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G5, tmp); 193 } 194 195 if (kpath & RF_B) { 196 rtw89_phy_write32_mask(rtwdev, R_COEF_SEL_C1, B_COEF_SEL_EN, 0x1); 197 rtw89_phy_write32_mask(rtwdev, R_COEF_SEL_C1, B_COEF_SEL_IQC_V1, idx); 198 rtw89_phy_write32_mask(rtwdev, R_COEF_SEL_C1, B_COEF_SEL_MDPD_V1, idx); 199 rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT, RR_TXG_SEL, 0x4 | idx); 200 201 tmp = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL_C1, BIT(0)); 202 rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT_C1, B_CFIR_LUT_G3, tmp); 203 tmp = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL_C1, BIT(1)); 204 rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT_C1, B_CFIR_LUT_G5, tmp); 205 } 206 } 207 208 static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev, 209 const struct rtw89_chan *chan, u8 path) 210 { 211 struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc; 212 struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {}; 213 u8 tbl_sel; 214 215 for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) { 216 struct rtw89_rfk_chan_desc *p = &desc[tbl_sel]; 217 218 p->ch = rfk_mcc->data[path].ch[tbl_sel]; 219 220 p->has_band = true; 221 p->band = rfk_mcc->data[path].band[tbl_sel]; 222 223 p->has_bw = true; 224 p->bw = rfk_mcc->data[path].bw[tbl_sel]; 225 } 226 227 tbl_sel = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan); 228 229 rfk_mcc->data[path].ch[tbl_sel] = chan->channel; 230 rfk_mcc->data[path].band[tbl_sel] = chan->band_type; 231 rfk_mcc->data[path].bw[tbl_sel] = chan->band_width; 232 rfk_mcc->data[path].table_idx = tbl_sel; 233 234 return tbl_sel; 235 } 236 237 static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev) 238 { 239 const struct rtw89_chan *chan0, *chan1; 240 u8 s0_tbl, s1_tbl; 241 242 switch (rtwdev->mlo_dbcc_mode) { 243 default: 244 case MLO_2_PLUS_0_1RF: 245 chan0 = rtw89_mgnt_chan_get(rtwdev, 0); 246 chan1 = chan0; 247 break; 248 case MLO_0_PLUS_2_1RF: 249 chan1 = rtw89_mgnt_chan_get(rtwdev, 1); 250 chan0 = chan1; 251 break; 252 case MLO_1_PLUS_1_1RF: 253 chan0 = rtw89_mgnt_chan_get(rtwdev, 0); 254 chan1 = rtw89_mgnt_chan_get(rtwdev, 1); 255 break; 256 } 257 258 s0_tbl = rtw8922a_chlk_reload_sel_tbl(rtwdev, chan0, 0); 259 s1_tbl = rtw8922a_chlk_reload_sel_tbl(rtwdev, chan1, 1); 260 261 rtw8922a_chlk_ktbl_sel(rtwdev, RF_A, s0_tbl); 262 rtw8922a_chlk_ktbl_sel(rtwdev, RF_B, s1_tbl); 263 } 264 265 static void rtw8922a_rfk_mlo_ctrl(struct rtw89_dev *rtwdev) 266 { 267 enum _rf_syn_pow syn_pow; 268 269 if (!rtwdev->dbcc_en) 270 goto set_rfk_reload; 271 272 switch (rtwdev->mlo_dbcc_mode) { 273 case MLO_0_PLUS_2_1RF: 274 syn_pow = RF_SYN_OFF_ON; 275 break; 276 case MLO_0_PLUS_2_2RF: 277 case MLO_1_PLUS_1_2RF: 278 case MLO_2_PLUS_0_1RF: 279 case MLO_2_PLUS_0_2RF: 280 case MLO_2_PLUS_2_2RF: 281 case MLO_DBCC_NOT_SUPPORT: 282 default: 283 syn_pow = RF_SYN_ON_OFF; 284 break; 285 case MLO_1_PLUS_1_1RF: 286 case DBCC_LEGACY: 287 syn_pow = RF_SYN_ALLON; 288 break; 289 } 290 291 rtw8922a_set_syn01(rtwdev, syn_pow); 292 293 set_rfk_reload: 294 rtw8922a_chlk_reload(rtwdev); 295 } 296 297 static void rtw8922a_rfk_pll_init(struct rtw89_dev *rtwdev) 298 { 299 int ret; 300 u8 tmp; 301 302 ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_PLL_1, &tmp); 303 if (ret) 304 return; 305 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_PLL_1, tmp | 0xf8, 0xFF); 306 if (ret) 307 return; 308 309 ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_APBT, &tmp); 310 if (ret) 311 return; 312 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_APBT, tmp & ~0x60, 0xFF); 313 if (ret) 314 return; 315 316 ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_XTAL_PLL, &tmp); 317 if (ret) 318 return; 319 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_PLL, tmp | 0x38, 0xFF); 320 if (ret) 321 return; 322 } 323 324 void rtw8922a_rfk_hw_init(struct rtw89_dev *rtwdev) 325 { 326 if (rtwdev->dbcc_en) 327 rtw8922a_rfk_mlo_ctrl(rtwdev); 328 329 rtw8922a_rfk_pll_init(rtwdev); 330 } 331 332 void rtw8922a_pre_set_channel_rf(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 333 { 334 bool mlo_1_1; 335 336 if (!rtwdev->dbcc_en) 337 return; 338 339 mlo_1_1 = rtw89_is_mlo_1_1(rtwdev); 340 if (mlo_1_1) 341 rtw8922a_set_syn01(rtwdev, RF_SYN_ALLON); 342 else if (phy_idx == RTW89_PHY_0) 343 rtw8922a_set_syn01(rtwdev, RF_SYN_ON_OFF); 344 else 345 rtw8922a_set_syn01(rtwdev, RF_SYN_OFF_ON); 346 347 fsleep(1000); 348 } 349 350 void rtw8922a_post_set_channel_rf(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 351 { 352 rtw8922a_rfk_mlo_ctrl(rtwdev); 353 } 354