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