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