1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2019-2022 Realtek Corporation 3 */ 4 5 #include "coex.h" 6 #include "fw.h" 7 #include "mac.h" 8 #include "phy.h" 9 #include "reg.h" 10 #include "rtw8852b.h" 11 #include "rtw8852b_table.h" 12 #include "txrx.h" 13 14 static const struct rtw89_dle_mem rtw8852b_dle_mem_pcie[] = { 15 [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6, 16 &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6, 17 &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18, 18 &rtw89_mac_size.ple_qt58}, 19 [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9, 20 &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4, 21 &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13, 22 &rtw89_mac_size.ple_qt13}, 23 [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, 24 NULL}, 25 }; 26 27 static void rtw8852be_efuse_parsing(struct rtw89_efuse *efuse, 28 struct rtw8852b_efuse *map) 29 { 30 ether_addr_copy(efuse->addr, map->e.mac_addr); 31 efuse->rfe_type = map->rfe_type; 32 efuse->xtal_cap = map->xtal_k; 33 } 34 35 static void rtw8852b_efuse_parsing_tssi(struct rtw89_dev *rtwdev, 36 struct rtw8852b_efuse *map) 37 { 38 struct rtw89_tssi_info *tssi = &rtwdev->tssi; 39 struct rtw8852b_tssi_offset *ofst[] = {&map->path_a_tssi, &map->path_b_tssi}; 40 u8 i, j; 41 42 tssi->thermal[RF_PATH_A] = map->path_a_therm; 43 tssi->thermal[RF_PATH_B] = map->path_b_therm; 44 45 for (i = 0; i < RF_PATH_NUM_8852B; i++) { 46 memcpy(tssi->tssi_cck[i], ofst[i]->cck_tssi, 47 sizeof(ofst[i]->cck_tssi)); 48 49 for (j = 0; j < TSSI_CCK_CH_GROUP_NUM; j++) 50 rtw89_debug(rtwdev, RTW89_DBG_TSSI, 51 "[TSSI][EFUSE] path=%d cck[%d]=0x%x\n", 52 i, j, tssi->tssi_cck[i][j]); 53 54 memcpy(tssi->tssi_mcs[i], ofst[i]->bw40_tssi, 55 sizeof(ofst[i]->bw40_tssi)); 56 memcpy(tssi->tssi_mcs[i] + TSSI_MCS_2G_CH_GROUP_NUM, 57 ofst[i]->bw40_1s_tssi_5g, sizeof(ofst[i]->bw40_1s_tssi_5g)); 58 59 for (j = 0; j < TSSI_MCS_CH_GROUP_NUM; j++) 60 rtw89_debug(rtwdev, RTW89_DBG_TSSI, 61 "[TSSI][EFUSE] path=%d mcs[%d]=0x%x\n", 62 i, j, tssi->tssi_mcs[i][j]); 63 } 64 } 65 66 static bool _decode_efuse_gain(u8 data, s8 *high, s8 *low) 67 { 68 if (high) 69 *high = sign_extend32(FIELD_GET(GENMASK(7, 4), data), 3); 70 if (low) 71 *low = sign_extend32(FIELD_GET(GENMASK(3, 0), data), 3); 72 73 return data != 0xff; 74 } 75 76 static void rtw8852b_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev, 77 struct rtw8852b_efuse *map) 78 { 79 struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain; 80 bool valid = false; 81 82 valid |= _decode_efuse_gain(map->rx_gain_2g_cck, 83 &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_CCK], 84 &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_2G_CCK]); 85 valid |= _decode_efuse_gain(map->rx_gain_2g_ofdm, 86 &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_OFDM], 87 &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_2G_OFDM]); 88 valid |= _decode_efuse_gain(map->rx_gain_5g_low, 89 &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_LOW], 90 &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_5G_LOW]); 91 valid |= _decode_efuse_gain(map->rx_gain_5g_mid, 92 &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_MID], 93 &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_5G_MID]); 94 valid |= _decode_efuse_gain(map->rx_gain_5g_high, 95 &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_HIGH], 96 &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_5G_HIGH]); 97 98 gain->offset_valid = valid; 99 } 100 101 static int rtw8852b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map) 102 { 103 struct rtw89_efuse *efuse = &rtwdev->efuse; 104 struct rtw8852b_efuse *map; 105 106 map = (struct rtw8852b_efuse *)log_map; 107 108 efuse->country_code[0] = map->country_code[0]; 109 efuse->country_code[1] = map->country_code[1]; 110 rtw8852b_efuse_parsing_tssi(rtwdev, map); 111 rtw8852b_efuse_parsing_gain_offset(rtwdev, map); 112 113 switch (rtwdev->hci.type) { 114 case RTW89_HCI_TYPE_PCIE: 115 rtw8852be_efuse_parsing(efuse, map); 116 break; 117 default: 118 return -EOPNOTSUPP; 119 } 120 121 rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); 122 123 return 0; 124 } 125 126 static void rtw8852b_phycap_parsing_power_cal(struct rtw89_dev *rtwdev, u8 *phycap_map) 127 { 128 #define PWR_K_CHK_OFFSET 0x5E9 129 #define PWR_K_CHK_VALUE 0xAA 130 u32 offset = PWR_K_CHK_OFFSET - rtwdev->chip->phycap_addr; 131 132 if (phycap_map[offset] == PWR_K_CHK_VALUE) 133 rtwdev->efuse.power_k_valid = true; 134 } 135 136 static void rtw8852b_phycap_parsing_tssi(struct rtw89_dev *rtwdev, u8 *phycap_map) 137 { 138 struct rtw89_tssi_info *tssi = &rtwdev->tssi; 139 static const u32 tssi_trim_addr[RF_PATH_NUM_8852B] = {0x5D6, 0x5AB}; 140 u32 addr = rtwdev->chip->phycap_addr; 141 bool pg = false; 142 u32 ofst; 143 u8 i, j; 144 145 for (i = 0; i < RF_PATH_NUM_8852B; i++) { 146 for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++) { 147 /* addrs are in decreasing order */ 148 ofst = tssi_trim_addr[i] - addr - j; 149 tssi->tssi_trim[i][j] = phycap_map[ofst]; 150 151 if (phycap_map[ofst] != 0xff) 152 pg = true; 153 } 154 } 155 156 if (!pg) { 157 memset(tssi->tssi_trim, 0, sizeof(tssi->tssi_trim)); 158 rtw89_debug(rtwdev, RTW89_DBG_TSSI, 159 "[TSSI][TRIM] no PG, set all trim info to 0\n"); 160 } 161 162 for (i = 0; i < RF_PATH_NUM_8852B; i++) 163 for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++) 164 rtw89_debug(rtwdev, RTW89_DBG_TSSI, 165 "[TSSI] path=%d idx=%d trim=0x%x addr=0x%x\n", 166 i, j, tssi->tssi_trim[i][j], 167 tssi_trim_addr[i] - j); 168 } 169 170 static void rtw8852b_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev, 171 u8 *phycap_map) 172 { 173 struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; 174 static const u32 thm_trim_addr[RF_PATH_NUM_8852B] = {0x5DF, 0x5DC}; 175 u32 addr = rtwdev->chip->phycap_addr; 176 u8 i; 177 178 for (i = 0; i < RF_PATH_NUM_8852B; i++) { 179 info->thermal_trim[i] = phycap_map[thm_trim_addr[i] - addr]; 180 181 rtw89_debug(rtwdev, RTW89_DBG_RFK, 182 "[THERMAL][TRIM] path=%d thermal_trim=0x%x\n", 183 i, info->thermal_trim[i]); 184 185 if (info->thermal_trim[i] != 0xff) 186 info->pg_thermal_trim = true; 187 } 188 } 189 190 static void rtw8852b_thermal_trim(struct rtw89_dev *rtwdev) 191 { 192 #define __thm_setting(raw) \ 193 ({ \ 194 u8 __v = (raw); \ 195 ((__v & 0x1) << 3) | ((__v & 0x1f) >> 1); \ 196 }) 197 struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; 198 u8 i, val; 199 200 if (!info->pg_thermal_trim) { 201 rtw89_debug(rtwdev, RTW89_DBG_RFK, 202 "[THERMAL][TRIM] no PG, do nothing\n"); 203 204 return; 205 } 206 207 for (i = 0; i < RF_PATH_NUM_8852B; i++) { 208 val = __thm_setting(info->thermal_trim[i]); 209 rtw89_write_rf(rtwdev, i, RR_TM2, RR_TM2_OFF, val); 210 211 rtw89_debug(rtwdev, RTW89_DBG_RFK, 212 "[THERMAL][TRIM] path=%d thermal_setting=0x%x\n", 213 i, val); 214 } 215 #undef __thm_setting 216 } 217 218 static void rtw8852b_phycap_parsing_pa_bias_trim(struct rtw89_dev *rtwdev, 219 u8 *phycap_map) 220 { 221 struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; 222 static const u32 pabias_trim_addr[RF_PATH_NUM_8852B] = {0x5DE, 0x5DB}; 223 u32 addr = rtwdev->chip->phycap_addr; 224 u8 i; 225 226 for (i = 0; i < RF_PATH_NUM_8852B; i++) { 227 info->pa_bias_trim[i] = phycap_map[pabias_trim_addr[i] - addr]; 228 229 rtw89_debug(rtwdev, RTW89_DBG_RFK, 230 "[PA_BIAS][TRIM] path=%d pa_bias_trim=0x%x\n", 231 i, info->pa_bias_trim[i]); 232 233 if (info->pa_bias_trim[i] != 0xff) 234 info->pg_pa_bias_trim = true; 235 } 236 } 237 238 static void rtw8852b_pa_bias_trim(struct rtw89_dev *rtwdev) 239 { 240 struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; 241 u8 pabias_2g, pabias_5g; 242 u8 i; 243 244 if (!info->pg_pa_bias_trim) { 245 rtw89_debug(rtwdev, RTW89_DBG_RFK, 246 "[PA_BIAS][TRIM] no PG, do nothing\n"); 247 248 return; 249 } 250 251 for (i = 0; i < RF_PATH_NUM_8852B; i++) { 252 pabias_2g = FIELD_GET(GENMASK(3, 0), info->pa_bias_trim[i]); 253 pabias_5g = FIELD_GET(GENMASK(7, 4), info->pa_bias_trim[i]); 254 255 rtw89_debug(rtwdev, RTW89_DBG_RFK, 256 "[PA_BIAS][TRIM] path=%d 2G=0x%x 5G=0x%x\n", 257 i, pabias_2g, pabias_5g); 258 259 rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXG, pabias_2g); 260 rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXA, pabias_5g); 261 } 262 } 263 264 static void rtw8852b_phycap_parsing_gain_comp(struct rtw89_dev *rtwdev, u8 *phycap_map) 265 { 266 static const u32 comp_addrs[][RTW89_SUBBAND_2GHZ_5GHZ_NR] = { 267 {0x5BB, 0x5BA, 0, 0x5B9, 0x5B8}, 268 {0x590, 0x58F, 0, 0x58E, 0x58D}, 269 }; 270 struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain; 271 u32 phycap_addr = rtwdev->chip->phycap_addr; 272 bool valid = false; 273 int path, i; 274 u8 data; 275 276 for (path = 0; path < 2; path++) 277 for (i = 0; i < RTW89_SUBBAND_2GHZ_5GHZ_NR; i++) { 278 if (comp_addrs[path][i] == 0) 279 continue; 280 281 data = phycap_map[comp_addrs[path][i] - phycap_addr]; 282 valid |= _decode_efuse_gain(data, NULL, 283 &gain->comp[path][i]); 284 } 285 286 gain->comp_valid = valid; 287 } 288 289 static int rtw8852b_read_phycap(struct rtw89_dev *rtwdev, u8 *phycap_map) 290 { 291 rtw8852b_phycap_parsing_power_cal(rtwdev, phycap_map); 292 rtw8852b_phycap_parsing_tssi(rtwdev, phycap_map); 293 rtw8852b_phycap_parsing_thermal_trim(rtwdev, phycap_map); 294 rtw8852b_phycap_parsing_pa_bias_trim(rtwdev, phycap_map); 295 rtw8852b_phycap_parsing_gain_comp(rtwdev, phycap_map); 296 297 return 0; 298 } 299 300 static void rtw8852b_power_trim(struct rtw89_dev *rtwdev) 301 { 302 rtw8852b_thermal_trim(rtwdev); 303 rtw8852b_pa_bias_trim(rtwdev); 304 } 305 306 static u32 rtw8852b_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, 307 enum rtw89_phy_idx phy_idx, s16 ref) 308 { 309 const u16 tssi_16dbm_cw = 0x12c; 310 const u8 base_cw_0db = 0x27; 311 const s8 ofst_int = 0; 312 s16 pwr_s10_3; 313 s16 rf_pwr_cw; 314 u16 bb_pwr_cw; 315 u32 pwr_cw; 316 u32 tssi_ofst_cw; 317 318 pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3); 319 bb_pwr_cw = FIELD_GET(GENMASK(2, 0), pwr_s10_3); 320 rf_pwr_cw = FIELD_GET(GENMASK(8, 3), pwr_s10_3); 321 rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63); 322 pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw; 323 324 tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)); 325 rtw89_debug(rtwdev, RTW89_DBG_TXPWR, 326 "[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n", 327 tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw); 328 329 return FIELD_PREP(B_DPD_TSSI_CW, tssi_ofst_cw) | 330 FIELD_PREP(B_DPD_PWR_CW, pwr_cw) | 331 FIELD_PREP(B_DPD_REF, ref); 332 } 333 334 static void rtw8852b_set_txpwr_ref(struct rtw89_dev *rtwdev, 335 enum rtw89_phy_idx phy_idx) 336 { 337 static const u32 addr[RF_PATH_NUM_8852B] = {0x5800, 0x7800}; 338 const u32 mask = B_DPD_TSSI_CW | B_DPD_PWR_CW | B_DPD_REF; 339 const u8 ofst_ofdm = 0x4; 340 const u8 ofst_cck = 0x8; 341 const s16 ref_ofdm = 0; 342 const s16 ref_cck = 0; 343 u32 val; 344 u8 i; 345 346 rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr reference\n"); 347 348 rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL, 349 B_AX_PWR_REF, 0x0); 350 351 rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n"); 352 val = rtw8852b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm); 353 354 for (i = 0; i < RF_PATH_NUM_8852B; i++) 355 rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, 356 phy_idx); 357 358 rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n"); 359 val = rtw8852b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck); 360 361 for (i = 0; i < RF_PATH_NUM_8852B; i++) 362 rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, 363 phy_idx); 364 } 365 366 static void rtw8852b_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev, 367 u8 tx_shape_idx, 368 enum rtw89_phy_idx phy_idx) 369 { 370 #define __DFIR_CFG_ADDR(i) (R_TXFIR0 + ((i) << 2)) 371 #define __DFIR_CFG_MASK 0xffffffff 372 #define __DFIR_CFG_NR 8 373 #define __DECL_DFIR_PARAM(_name, _val...) \ 374 static const u32 param_ ## _name[] = {_val}; \ 375 static_assert(ARRAY_SIZE(param_ ## _name) == __DFIR_CFG_NR) 376 377 __DECL_DFIR_PARAM(flat, 378 0x023D23FF, 0x0029B354, 0x000FC1C8, 0x00FDB053, 379 0x00F86F9A, 0x06FAEF92, 0x00FE5FCC, 0x00FFDFF5); 380 __DECL_DFIR_PARAM(sharp, 381 0x023D83FF, 0x002C636A, 0x0013F204, 0x00008090, 382 0x00F87FB0, 0x06F99F83, 0x00FDBFBA, 0x00003FF5); 383 __DECL_DFIR_PARAM(sharp_14, 384 0x023B13FF, 0x001C42DE, 0x00FDB0AD, 0x00F60F6E, 385 0x00FD8F92, 0x0602D011, 0x0001C02C, 0x00FFF00A); 386 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); 387 u8 ch = chan->channel; 388 const u32 *param; 389 u32 addr; 390 int i; 391 392 if (ch > 14) { 393 rtw89_warn(rtwdev, 394 "set tx shape dfir by unknown ch: %d on 2G\n", ch); 395 return; 396 } 397 398 if (ch == 14) 399 param = param_sharp_14; 400 else 401 param = tx_shape_idx == 0 ? param_flat : param_sharp; 402 403 for (i = 0; i < __DFIR_CFG_NR; i++) { 404 addr = __DFIR_CFG_ADDR(i); 405 rtw89_debug(rtwdev, RTW89_DBG_TXPWR, 406 "set tx shape dfir: 0x%x: 0x%x\n", addr, param[i]); 407 rtw89_phy_write32_idx(rtwdev, addr, __DFIR_CFG_MASK, param[i], 408 phy_idx); 409 } 410 411 #undef __DECL_DFIR_PARAM 412 #undef __DFIR_CFG_NR 413 #undef __DFIR_CFG_MASK 414 #undef __DECL_CFG_ADDR 415 } 416 417 static void rtw8852b_set_tx_shape(struct rtw89_dev *rtwdev, 418 const struct rtw89_chan *chan, 419 enum rtw89_phy_idx phy_idx) 420 { 421 u8 band = chan->band_type; 422 u8 regd = rtw89_regd_get(rtwdev, band); 423 u8 tx_shape_cck = rtw89_8852b_tx_shape[band][RTW89_RS_CCK][regd]; 424 u8 tx_shape_ofdm = rtw89_8852b_tx_shape[band][RTW89_RS_OFDM][regd]; 425 426 if (band == RTW89_BAND_2G) 427 rtw8852b_bb_set_tx_shape_dfir(rtwdev, tx_shape_cck, phy_idx); 428 429 rtw89_phy_write32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG, 430 tx_shape_ofdm); 431 } 432 433 static void rtw8852b_set_txpwr(struct rtw89_dev *rtwdev, 434 const struct rtw89_chan *chan, 435 enum rtw89_phy_idx phy_idx) 436 { 437 rtw89_phy_set_txpwr_byrate(rtwdev, chan, phy_idx); 438 rtw89_phy_set_txpwr_offset(rtwdev, chan, phy_idx); 439 rtw8852b_set_tx_shape(rtwdev, chan, phy_idx); 440 rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx); 441 rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx); 442 } 443 444 static void rtw8852b_set_txpwr_ctrl(struct rtw89_dev *rtwdev, 445 enum rtw89_phy_idx phy_idx) 446 { 447 rtw8852b_set_txpwr_ref(rtwdev, phy_idx); 448 } 449 450 static 451 void rtw8852b_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, 452 s8 pw_ofst, enum rtw89_mac_idx mac_idx) 453 { 454 u32 reg; 455 456 if (pw_ofst < -16 || pw_ofst > 15) { 457 rtw89_warn(rtwdev, "[ULTB] Err pwr_offset=%d\n", pw_ofst); 458 return; 459 } 460 461 reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx); 462 rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN); 463 464 reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx); 465 rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, pw_ofst); 466 467 pw_ofst = max_t(s8, pw_ofst - 3, -16); 468 reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx); 469 rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, pw_ofst); 470 } 471 472 static int 473 rtw8852b_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 474 { 475 int ret; 476 477 ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL2, 0x07763333); 478 if (ret) 479 return ret; 480 481 ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_COEXT_CTRL, 0x01ebf000); 482 if (ret) 483 return ret; 484 485 ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL0, 0x0002f8ff); 486 if (ret) 487 return ret; 488 489 rtw8852b_set_txpwr_ul_tb_offset(rtwdev, 0, phy_idx == RTW89_PHY_1 ? 490 RTW89_MAC_1 : RTW89_MAC_0); 491 492 return 0; 493 } 494 495 static int rtw8852b_mac_enable_bb_rf(struct rtw89_dev *rtwdev) 496 { 497 int ret; 498 499 rtw89_write8_set(rtwdev, R_AX_SYS_FUNC_EN, 500 B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN); 501 rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0, B_AX_REG_ZCDC_H_MASK, 0x1); 502 rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); 503 rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); 504 rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); 505 506 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0xC7, 507 FULL_BIT_MASK); 508 if (ret) 509 return ret; 510 511 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, 0xC7, 512 FULL_BIT_MASK); 513 if (ret) 514 return ret; 515 516 rtw89_write8(rtwdev, R_AX_PHYREG_SET, PHYREG_SET_XYN_CYCLE); 517 518 return 0; 519 } 520 521 static int rtw8852b_mac_disable_bb_rf(struct rtw89_dev *rtwdev) 522 { 523 u8 wl_rfc_s0; 524 u8 wl_rfc_s1; 525 int ret; 526 527 rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, 528 B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN); 529 530 ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, &wl_rfc_s0); 531 if (ret) 532 return ret; 533 wl_rfc_s0 &= ~XTAL_SI_RF00S_EN; 534 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, wl_rfc_s0, 535 FULL_BIT_MASK); 536 if (ret) 537 return ret; 538 539 ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, &wl_rfc_s1); 540 if (ret) 541 return ret; 542 wl_rfc_s1 &= ~XTAL_SI_RF10S_EN; 543 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, wl_rfc_s1, 544 FULL_BIT_MASK); 545 return ret; 546 } 547 548 static const struct rtw89_chip_ops rtw8852b_chip_ops = { 549 .enable_bb_rf = rtw8852b_mac_enable_bb_rf, 550 .disable_bb_rf = rtw8852b_mac_disable_bb_rf, 551 .read_efuse = rtw8852b_read_efuse, 552 .read_phycap = rtw8852b_read_phycap, 553 .power_trim = rtw8852b_power_trim, 554 .set_txpwr = rtw8852b_set_txpwr, 555 .set_txpwr_ctrl = rtw8852b_set_txpwr_ctrl, 556 .init_txpwr_unit = rtw8852b_init_txpwr_unit, 557 }; 558 559 const struct rtw89_chip_info rtw8852b_chip_info = { 560 .chip_id = RTL8852B, 561 .ops = &rtw8852b_chip_ops, 562 .fifo_size = 196608, 563 .dle_scc_rsvd_size = 98304, 564 .dle_mem = rtw8852b_dle_mem_pcie, 565 .sec_ctrl_efuse_size = 4, 566 .physical_efuse_size = 1216, 567 .logical_efuse_size = 2048, 568 .limit_efuse_size = 1280, 569 .dav_phy_efuse_size = 96, 570 .dav_log_efuse_size = 16, 571 .phycap_addr = 0x580, 572 .phycap_size = 128, 573 .dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) | 574 BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) | 575 BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI), 576 }; 577 EXPORT_SYMBOL(rtw8852b_chip_info); 578 579 MODULE_FIRMWARE("rtw89/rtw8852b_fw.bin"); 580 MODULE_AUTHOR("Realtek Corporation"); 581 MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852B driver"); 582 MODULE_LICENSE("Dual BSD/GPL"); 583