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