1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2009-2012 Realtek Corporation.*/ 3 4 #include "../wifi.h" 5 #include "reg.h" 6 #include "def.h" 7 #include "phy.h" 8 #include "rf.h" 9 #include "dm.h" 10 11 static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw); 12 13 void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) 14 { 15 struct rtl_priv *rtlpriv = rtl_priv(hw); 16 struct rtl_phy *rtlphy = &(rtlpriv->phy); 17 18 switch (bandwidth) { 19 case HT_CHANNEL_WIDTH_20: 20 rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & 21 0xfffff3ff) | 0x0400); 22 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, 23 rtlphy->rfreg_chnlval[0]); 24 break; 25 case HT_CHANNEL_WIDTH_20_40: 26 rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & 27 0xfffff3ff)); 28 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, 29 rtlphy->rfreg_chnlval[0]); 30 break; 31 default: 32 pr_err("unknown bandwidth: %#X\n", bandwidth); 33 break; 34 } 35 } 36 37 void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, 38 u8 *ppowerlevel) 39 { 40 struct rtl_priv *rtlpriv = rtl_priv(hw); 41 struct rtl_phy *rtlphy = &(rtlpriv->phy); 42 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 43 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 44 u32 tx_agc[2] = {0, 0}, tmpval; 45 bool turbo_scanoff = false; 46 u8 idx1, idx2; 47 u8 *ptr; 48 49 if (rtlefuse->eeprom_regulatory != 0) 50 turbo_scanoff = true; 51 52 if (mac->act_scanning) { 53 tx_agc[RF90_PATH_A] = 0x3f3f3f3f; 54 tx_agc[RF90_PATH_B] = 0x3f3f3f3f; 55 56 if (turbo_scanoff) { 57 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { 58 tx_agc[idx1] = ppowerlevel[idx1] | 59 (ppowerlevel[idx1] << 8) | 60 (ppowerlevel[idx1] << 16) | 61 (ppowerlevel[idx1] << 24); 62 } 63 } 64 } else { 65 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { 66 tx_agc[idx1] = ppowerlevel[idx1] | 67 (ppowerlevel[idx1] << 8) | 68 (ppowerlevel[idx1] << 16) | 69 (ppowerlevel[idx1] << 24); 70 } 71 72 if (rtlefuse->eeprom_regulatory == 0) { 73 tmpval = (rtlphy->mcs_offset[0][6]) + 74 (rtlphy->mcs_offset[0][7] << 8); 75 tx_agc[RF90_PATH_A] += tmpval; 76 77 tmpval = (rtlphy->mcs_offset[0][14]) + 78 (rtlphy->mcs_offset[0][15] << 24); 79 tx_agc[RF90_PATH_B] += tmpval; 80 } 81 } 82 83 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { 84 ptr = (u8 *) (&(tx_agc[idx1])); 85 for (idx2 = 0; idx2 < 4; idx2++) { 86 if (*ptr > RF6052_MAX_TX_PWR) 87 *ptr = RF6052_MAX_TX_PWR; 88 ptr++; 89 } 90 } 91 92 tmpval = tx_agc[RF90_PATH_A] & 0xff; 93 rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); 94 95 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 96 "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", 97 tmpval, RTXAGC_A_CCK1_MCS32); 98 99 tmpval = tx_agc[RF90_PATH_A] >> 8; 100 101 tmpval = tmpval & 0xff00ffff; 102 103 rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); 104 105 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 106 "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", 107 tmpval, RTXAGC_B_CCK11_A_CCK2_11); 108 109 tmpval = tx_agc[RF90_PATH_B] >> 24; 110 rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); 111 112 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 113 "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", 114 tmpval, RTXAGC_B_CCK11_A_CCK2_11); 115 116 tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; 117 rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); 118 119 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 120 "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", 121 tmpval, RTXAGC_B_CCK1_55_MCS32); 122 } 123 124 static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, 125 u8 *ppowerlevel, u8 channel, 126 u32 *ofdmbase, u32 *mcsbase) 127 { 128 struct rtl_priv *rtlpriv = rtl_priv(hw); 129 struct rtl_phy *rtlphy = &(rtlpriv->phy); 130 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 131 u32 powerbase0, powerbase1; 132 u8 legacy_pwrdiff, ht20_pwrdiff; 133 u8 i, powerlevel[2]; 134 135 for (i = 0; i < 2; i++) { 136 powerlevel[i] = ppowerlevel[i]; 137 legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; 138 powerbase0 = powerlevel[i] + legacy_pwrdiff; 139 140 powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | 141 (powerbase0 << 8) | powerbase0; 142 *(ofdmbase + i) = powerbase0; 143 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 144 " [OFDM power base index rf(%c) = 0x%x]\n", 145 i == 0 ? 'A' : 'B', *(ofdmbase + i)); 146 } 147 148 for (i = 0; i < 2; i++) { 149 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { 150 ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; 151 powerlevel[i] += ht20_pwrdiff; 152 } 153 powerbase1 = powerlevel[i]; 154 powerbase1 = (powerbase1 << 24) | 155 (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; 156 157 *(mcsbase + i) = powerbase1; 158 159 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 160 " [MCS power base index rf(%c) = 0x%x]\n", 161 i == 0 ? 'A' : 'B', *(mcsbase + i)); 162 } 163 } 164 165 static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, 166 u8 channel, u8 index, 167 u32 *powerbase0, 168 u32 *powerbase1, 169 u32 *p_outwriteval) 170 { 171 struct rtl_priv *rtlpriv = rtl_priv(hw); 172 struct rtl_phy *rtlphy = &(rtlpriv->phy); 173 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 174 u8 i, chnlgroup = 0, pwr_diff_limit[4]; 175 u32 writeval, customer_limit, rf; 176 177 for (rf = 0; rf < 2; rf++) { 178 switch (rtlefuse->eeprom_regulatory) { 179 case 0: 180 chnlgroup = 0; 181 182 writeval = rtlphy->mcs_offset[chnlgroup][index + 183 (rf ? 8 : 0)] 184 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 185 186 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 187 "RTK better performance, writeval(%c) = 0x%x\n", 188 rf == 0 ? 'A' : 'B', writeval); 189 break; 190 case 1: 191 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { 192 writeval = ((index < 2) ? powerbase0[rf] : 193 powerbase1[rf]); 194 195 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 196 "Realtek regulatory, 40MHz, writeval(%c) = 0x%x\n", 197 rf == 0 ? 'A' : 'B', writeval); 198 } else { 199 if (rtlphy->pwrgroup_cnt == 1) 200 chnlgroup = 0; 201 if (rtlphy->pwrgroup_cnt >= 3) { 202 if (channel <= 3) 203 chnlgroup = 0; 204 else if (channel >= 4 && channel <= 9) 205 chnlgroup = 1; 206 else if (channel > 9) 207 chnlgroup = 2; 208 if (rtlphy->pwrgroup_cnt == 4) 209 chnlgroup++; 210 } 211 212 writeval = rtlphy->mcs_offset[chnlgroup] 213 [index + (rf ? 8 : 0)] + ((index < 2) ? 214 powerbase0[rf] : 215 powerbase1[rf]); 216 217 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 218 "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", 219 rf == 0 ? 'A' : 'B', writeval); 220 } 221 break; 222 case 2: 223 writeval = 224 ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 225 226 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 227 "Better regulatory, writeval(%c) = 0x%x\n", 228 rf == 0 ? 'A' : 'B', writeval); 229 break; 230 case 3: 231 chnlgroup = 0; 232 233 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { 234 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 235 "customer's limit, 40MHz rf(%c) = 0x%x\n", 236 rf == 0 ? 'A' : 'B', 237 rtlefuse->pwrgroup_ht40[rf][channel - 238 1]); 239 } else { 240 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 241 "customer's limit, 20MHz rf(%c) = 0x%x\n", 242 rf == 0 ? 'A' : 'B', 243 rtlefuse->pwrgroup_ht20[rf][channel - 244 1]); 245 } 246 for (i = 0; i < 4; i++) { 247 pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset 248 [chnlgroup][index + 249 (rf ? 8 : 0)] & (0x7f << (i * 8))) >> 250 (i * 8)); 251 252 if (rtlphy->current_chan_bw == 253 HT_CHANNEL_WIDTH_20_40) { 254 if (pwr_diff_limit[i] > 255 rtlefuse-> 256 pwrgroup_ht40[rf][channel - 1]) 257 pwr_diff_limit[i] = 258 rtlefuse->pwrgroup_ht40[rf] 259 [channel - 1]; 260 } else { 261 if (pwr_diff_limit[i] > 262 rtlefuse-> 263 pwrgroup_ht20[rf][channel - 1]) 264 pwr_diff_limit[i] = 265 rtlefuse->pwrgroup_ht20[rf] 266 [channel - 1]; 267 } 268 } 269 270 customer_limit = (pwr_diff_limit[3] << 24) | 271 (pwr_diff_limit[2] << 16) | 272 (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); 273 274 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 275 "Customer's limit rf(%c) = 0x%x\n", 276 rf == 0 ? 'A' : 'B', customer_limit); 277 278 writeval = customer_limit + 279 ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 280 281 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 282 "Customer, writeval rf(%c)= 0x%x\n", 283 rf == 0 ? 'A' : 'B', writeval); 284 break; 285 default: 286 chnlgroup = 0; 287 writeval = rtlphy->mcs_offset[chnlgroup] 288 [index + (rf ? 8 : 0)] 289 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 290 291 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 292 "RTK better performance, writeval rf(%c) = 0x%x\n", 293 rf == 0 ? 'A' : 'B', writeval); 294 break; 295 } 296 297 if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) 298 writeval = writeval - 0x06060606; 299 else if (rtlpriv->dm.dynamic_txhighpower_lvl == 300 TXHIGHPWRLEVEL_BT2) 301 writeval = writeval - 0x0c0c0c0c; 302 *(p_outwriteval + rf) = writeval; 303 } 304 } 305 306 static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, 307 u8 index, u32 *value) 308 { 309 struct rtl_priv *rtlpriv = rtl_priv(hw); 310 struct rtl_phy *rtlphy = &(rtlpriv->phy); 311 312 u16 regoffset_a[6] = { 313 RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, 314 RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, 315 RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 316 }; 317 u16 regoffset_b[6] = { 318 RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, 319 RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, 320 RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 321 }; 322 u8 i, rf, pwr_val[4]; 323 u32 writeval; 324 u16 regoffset; 325 326 for (rf = 0; rf < 2; rf++) { 327 writeval = value[rf]; 328 for (i = 0; i < 4; i++) { 329 pwr_val[i] = (u8)((writeval & (0x7f << 330 (i * 8))) >> (i * 8)); 331 332 if (pwr_val[i] > RF6052_MAX_TX_PWR) 333 pwr_val[i] = RF6052_MAX_TX_PWR; 334 } 335 writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | 336 (pwr_val[1] << 8) | pwr_val[0]; 337 338 if (rf == 0) 339 regoffset = regoffset_a[index]; 340 else 341 regoffset = regoffset_b[index]; 342 rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); 343 344 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 345 "Set 0x%x = %08x\n", regoffset, writeval); 346 347 if (((get_rf_type(rtlphy) == RF_2T2R) && 348 (regoffset == RTXAGC_A_MCS15_MCS12 || 349 regoffset == RTXAGC_B_MCS15_MCS12)) || 350 ((get_rf_type(rtlphy) != RF_2T2R) && 351 (regoffset == RTXAGC_A_MCS07_MCS04 || 352 regoffset == RTXAGC_B_MCS07_MCS04))) { 353 354 writeval = pwr_val[3]; 355 if (regoffset == RTXAGC_A_MCS15_MCS12 || 356 regoffset == RTXAGC_A_MCS07_MCS04) 357 regoffset = 0xc90; 358 if (regoffset == RTXAGC_B_MCS15_MCS12 || 359 regoffset == RTXAGC_B_MCS07_MCS04) 360 regoffset = 0xc98; 361 362 for (i = 0; i < 3; i++) { 363 writeval = (writeval > 6) ? (writeval - 6) : 0; 364 rtl_write_byte(rtlpriv, (u32) (regoffset + i), 365 (u8)writeval); 366 } 367 } 368 } 369 } 370 371 void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, 372 u8 *ppowerlevel, u8 channel) 373 { 374 u32 writeval[2], powerbase0[2], powerbase1[2]; 375 u8 index; 376 377 rtl92c_phy_get_power_base(hw, ppowerlevel, 378 channel, &powerbase0[0], &powerbase1[0]); 379 380 for (index = 0; index < 6; index++) { 381 _rtl92c_get_txpower_writeval_by_regulatory(hw, 382 channel, index, 383 &powerbase0[0], 384 &powerbase1[0], 385 &writeval[0]); 386 387 _rtl92c_write_ofdm_power_reg(hw, index, &writeval[0]); 388 } 389 } 390 391 bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw) 392 { 393 struct rtl_priv *rtlpriv = rtl_priv(hw); 394 struct rtl_phy *rtlphy = &(rtlpriv->phy); 395 396 if (rtlphy->rf_type == RF_1T1R) 397 rtlphy->num_total_rfpath = 1; 398 else 399 rtlphy->num_total_rfpath = 2; 400 401 return _rtl92ce_phy_rf6052_config_parafile(hw); 402 403 } 404 405 static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw) 406 { 407 struct rtl_priv *rtlpriv = rtl_priv(hw); 408 struct rtl_phy *rtlphy = &(rtlpriv->phy); 409 u32 u4_regvalue = 0; 410 u8 rfpath; 411 bool rtstatus = true; 412 struct bb_reg_def *pphyreg; 413 414 for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { 415 416 pphyreg = &rtlphy->phyreg_def[rfpath]; 417 418 switch (rfpath) { 419 case RF90_PATH_A: 420 case RF90_PATH_C: 421 u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, 422 BRFSI_RFENV); 423 break; 424 case RF90_PATH_B: 425 case RF90_PATH_D: 426 u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, 427 BRFSI_RFENV << 16); 428 break; 429 } 430 431 rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); 432 udelay(1); 433 434 rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); 435 udelay(1); 436 437 rtl_set_bbreg(hw, pphyreg->rfhssi_para2, 438 B3WIREADDREAALENGTH, 0x0); 439 udelay(1); 440 441 rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); 442 udelay(1); 443 444 switch (rfpath) { 445 case RF90_PATH_A: 446 rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, 447 (enum radio_path)rfpath); 448 break; 449 case RF90_PATH_B: 450 rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, 451 (enum radio_path)rfpath); 452 break; 453 case RF90_PATH_C: 454 break; 455 case RF90_PATH_D: 456 break; 457 } 458 459 switch (rfpath) { 460 case RF90_PATH_A: 461 case RF90_PATH_C: 462 rtl_set_bbreg(hw, pphyreg->rfintfs, 463 BRFSI_RFENV, u4_regvalue); 464 break; 465 case RF90_PATH_B: 466 case RF90_PATH_D: 467 rtl_set_bbreg(hw, pphyreg->rfintfs, 468 BRFSI_RFENV << 16, u4_regvalue); 469 break; 470 } 471 472 if (!rtstatus) { 473 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, 474 "Radio[%d] Fail!!\n", rfpath); 475 return false; 476 } 477 478 } 479 480 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); 481 return rtstatus; 482 } 483