Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2013  Realtek Corporation.*/
0003 
0004 #include "../wifi.h"
0005 #include "reg.h"
0006 #include "def.h"
0007 #include "phy.h"
0008 #include "rf.h"
0009 #include "dm.h"
0010 
0011 static bool _rtl88e_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
0012 
0013 void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
0014 {
0015     struct rtl_priv *rtlpriv = rtl_priv(hw);
0016     struct rtl_phy *rtlphy = &(rtlpriv->phy);
0017 
0018     switch (bandwidth) {
0019     case HT_CHANNEL_WIDTH_20:
0020         rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
0021                          0xfffff3ff) | BIT(10) | BIT(11));
0022         rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
0023                   rtlphy->rfreg_chnlval[0]);
0024         break;
0025     case HT_CHANNEL_WIDTH_20_40:
0026         rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
0027                          0xfffff3ff) | BIT(10));
0028         rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
0029                   rtlphy->rfreg_chnlval[0]);
0030         break;
0031     default:
0032         pr_err("unknown bandwidth: %#X\n", bandwidth);
0033         break;
0034     }
0035 }
0036 
0037 void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
0038                        u8 *ppowerlevel)
0039 {
0040     struct rtl_priv *rtlpriv = rtl_priv(hw);
0041     struct rtl_phy *rtlphy = &(rtlpriv->phy);
0042     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0043     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
0044     u32 tx_agc[2] = {0, 0}, tmpval;
0045     bool turbo_scanoff = false;
0046     u8 idx1, idx2;
0047     u8 *ptr;
0048     u8 direction;
0049     u32 pwrtrac_value;
0050 
0051     if (rtlefuse->eeprom_regulatory != 0)
0052         turbo_scanoff = true;
0053 
0054     if (mac->act_scanning) {
0055         tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
0056         tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
0057 
0058         if (turbo_scanoff) {
0059             for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
0060                 tx_agc[idx1] = ppowerlevel[idx1] |
0061                     (ppowerlevel[idx1] << 8) |
0062                     (ppowerlevel[idx1] << 16) |
0063                     (ppowerlevel[idx1] << 24);
0064             }
0065         }
0066     } else {
0067         for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
0068             tx_agc[idx1] = ppowerlevel[idx1] |
0069                 (ppowerlevel[idx1] << 8) |
0070                 (ppowerlevel[idx1] << 16) |
0071                 (ppowerlevel[idx1] << 24);
0072         }
0073 
0074         if (rtlefuse->eeprom_regulatory == 0) {
0075             tmpval =
0076                 (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
0077                 (rtlphy->mcs_txpwrlevel_origoffset[0][7] <<
0078                  8);
0079             tx_agc[RF90_PATH_A] += tmpval;
0080 
0081             tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
0082                 (rtlphy->mcs_txpwrlevel_origoffset[0][15] <<
0083                  24);
0084             tx_agc[RF90_PATH_B] += tmpval;
0085         }
0086     }
0087 
0088     for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
0089         ptr = (u8 *)(&tx_agc[idx1]);
0090         for (idx2 = 0; idx2 < 4; idx2++) {
0091             if (*ptr > RF6052_MAX_TX_PWR)
0092                 *ptr = RF6052_MAX_TX_PWR;
0093             ptr++;
0094         }
0095     }
0096     rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
0097     if (direction == 1) {
0098         tx_agc[0] += pwrtrac_value;
0099         tx_agc[1] += pwrtrac_value;
0100     } else if (direction == 2) {
0101         tx_agc[0] -= pwrtrac_value;
0102         tx_agc[1] -= pwrtrac_value;
0103     }
0104     tmpval = tx_agc[RF90_PATH_A] & 0xff;
0105     rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
0106 
0107     RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0108         "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
0109          RTXAGC_A_CCK1_MCS32);
0110 
0111     tmpval = tx_agc[RF90_PATH_A] >> 8;
0112 
0113     /*tmpval = tmpval & 0xff00ffff;*/
0114 
0115     rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
0116 
0117     RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0118         "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
0119          RTXAGC_B_CCK11_A_CCK2_11);
0120 
0121     tmpval = tx_agc[RF90_PATH_B] >> 24;
0122     rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
0123 
0124     RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0125         "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
0126          RTXAGC_B_CCK11_A_CCK2_11);
0127 
0128     tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
0129     rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
0130 
0131     RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0132         "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
0133          RTXAGC_B_CCK1_55_MCS32);
0134 }
0135 
0136 static void rtl88e_phy_get_power_base(struct ieee80211_hw *hw,
0137                       u8 *ppowerlevel_ofdm,
0138                       u8 *ppowerlevel_bw20,
0139                       u8 *ppowerlevel_bw40, u8 channel,
0140                       u32 *ofdmbase, u32 *mcsbase)
0141 {
0142     struct rtl_priv *rtlpriv = rtl_priv(hw);
0143     struct rtl_phy *rtlphy = &(rtlpriv->phy);
0144     u32 powerbase0, powerbase1;
0145     u8 i, powerlevel[2];
0146 
0147     for (i = 0; i < 2; i++) {
0148         powerbase0 = ppowerlevel_ofdm[i];
0149 
0150         powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
0151             (powerbase0 << 8) | powerbase0;
0152         *(ofdmbase + i) = powerbase0;
0153         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0154             " [OFDM power base index rf(%c) = 0x%x]\n",
0155              ((i == 0) ? 'A' : 'B'), *(ofdmbase + i));
0156     }
0157 
0158     for (i = 0; i < 2; i++) {
0159         if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
0160             powerlevel[i] = ppowerlevel_bw20[i];
0161         else
0162             powerlevel[i] = ppowerlevel_bw40[i];
0163 
0164         powerbase1 = powerlevel[i];
0165         powerbase1 = (powerbase1 << 24) |
0166             (powerbase1 << 16) | (powerbase1 << 8) | powerbase1;
0167 
0168         *(mcsbase + i) = powerbase1;
0169 
0170         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0171             " [MCS power base index rf(%c) = 0x%x]\n",
0172              ((i == 0) ? 'A' : 'B'), *(mcsbase + i));
0173     }
0174 }
0175 
0176 static void _rtl88e_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
0177                                u8 channel, u8 index,
0178                                u32 *powerbase0,
0179                                u32 *powerbase1,
0180                                u32 *p_outwriteval)
0181 {
0182     struct rtl_priv *rtlpriv = rtl_priv(hw);
0183     struct rtl_phy *rtlphy = &(rtlpriv->phy);
0184     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
0185     u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff;
0186     u32 writeval, customer_limit, rf;
0187 
0188     for (rf = 0; rf < 2; rf++) {
0189         switch (rtlefuse->eeprom_regulatory) {
0190         case 0:
0191             chnlgroup = 0;
0192 
0193             writeval =
0194                 rtlphy->mcs_txpwrlevel_origoffset
0195                 [chnlgroup][index + (rf ? 8 : 0)]
0196                 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
0197 
0198             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0199                 "RTK better performance, writeval(%c) = 0x%x\n",
0200                 ((rf == 0) ? 'A' : 'B'), writeval);
0201             break;
0202         case 1:
0203             if (rtlphy->pwrgroup_cnt == 1) {
0204                 chnlgroup = 0;
0205             } else {
0206                 if (channel < 3)
0207                     chnlgroup = 0;
0208                 else if (channel < 6)
0209                     chnlgroup = 1;
0210                 else if (channel < 9)
0211                     chnlgroup = 2;
0212                 else if (channel < 12)
0213                     chnlgroup = 3;
0214                 else if (channel < 14)
0215                     chnlgroup = 4;
0216                 else if (channel == 14)
0217                     chnlgroup = 5;
0218             }
0219 
0220             writeval =
0221                 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
0222                 [index + (rf ? 8 : 0)] + ((index < 2) ?
0223                               powerbase0[rf] :
0224                               powerbase1[rf]);
0225 
0226             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0227                 "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",
0228                  ((rf == 0) ? 'A' : 'B'), writeval);
0229 
0230             break;
0231         case 2:
0232             writeval =
0233                 ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
0234 
0235             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0236                 "Better regulatory, writeval(%c) = 0x%x\n",
0237                 ((rf == 0) ? 'A' : 'B'), writeval);
0238             break;
0239         case 3:
0240             chnlgroup = 0;
0241 
0242             if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
0243                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0244                     "customer's limit, 40MHz rf(%c) = 0x%x\n",
0245                     ((rf == 0) ? 'A' : 'B'),
0246                     rtlefuse->pwrgroup_ht40[rf][channel -
0247                                     1]);
0248             } else {
0249                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0250                     "customer's limit, 20MHz rf(%c) = 0x%x\n",
0251                     ((rf == 0) ? 'A' : 'B'),
0252                     rtlefuse->pwrgroup_ht20[rf][channel -
0253                                     1]);
0254             }
0255 
0256             if (index < 2)
0257                 pwr_diff =
0258                    rtlefuse->txpwr_legacyhtdiff[rf][channel-1];
0259             else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
0260                 pwr_diff =
0261                     rtlefuse->txpwr_ht20diff[rf][channel-1];
0262 
0263             if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)
0264                 customer_pwr_diff =
0265                     rtlefuse->pwrgroup_ht40[rf][channel-1];
0266             else
0267                 customer_pwr_diff =
0268                     rtlefuse->pwrgroup_ht20[rf][channel-1];
0269 
0270             if (pwr_diff > customer_pwr_diff)
0271                 pwr_diff = 0;
0272             else
0273                 pwr_diff = customer_pwr_diff - pwr_diff;
0274 
0275             for (i = 0; i < 4; i++) {
0276                 pwr_diff_limit[i] =
0277                     (u8)((rtlphy->mcs_txpwrlevel_origoffset
0278                       [chnlgroup][index +
0279                       (rf ? 8 : 0)] & (0x7f <<
0280                       (i * 8))) >> (i * 8));
0281 
0282                 if (pwr_diff_limit[i] > pwr_diff)
0283                     pwr_diff_limit[i] = pwr_diff;
0284             }
0285 
0286             customer_limit = (pwr_diff_limit[3] << 24) |
0287                 (pwr_diff_limit[2] << 16) |
0288                 (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
0289 
0290             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0291                 "Customer's limit rf(%c) = 0x%x\n",
0292                  ((rf == 0) ? 'A' : 'B'), customer_limit);
0293 
0294             writeval = customer_limit +
0295                 ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
0296 
0297             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0298                 "Customer, writeval rf(%c)= 0x%x\n",
0299                  ((rf == 0) ? 'A' : 'B'), writeval);
0300             break;
0301         default:
0302             chnlgroup = 0;
0303             writeval =
0304                 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
0305                 [index + (rf ? 8 : 0)]
0306                 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
0307 
0308             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0309                 "RTK better performance, writeval rf(%c) = 0x%x\n",
0310                  ((rf == 0) ? 'A' : 'B'), writeval);
0311             break;
0312         }
0313 
0314         if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
0315             writeval = writeval - 0x06060606;
0316         else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
0317              TXHIGHPWRLEVEL_BT2)
0318             writeval = writeval - 0x0c0c0c0c;
0319         *(p_outwriteval + rf) = writeval;
0320     }
0321 }
0322 
0323 static void _rtl88e_write_ofdm_power_reg(struct ieee80211_hw *hw,
0324                      u8 index, u32 *value)
0325 {
0326     struct rtl_priv *rtlpriv = rtl_priv(hw);
0327     u16 regoffset_a[6] = {
0328         RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
0329         RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
0330         RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
0331     };
0332     u16 regoffset_b[6] = {
0333         RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
0334         RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
0335         RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
0336     };
0337     u8 i, rf, pwr_val[4];
0338     u32 writeval;
0339     u16 regoffset;
0340 
0341     for (rf = 0; rf < 2; rf++) {
0342         writeval = value[rf];
0343         for (i = 0; i < 4; i++) {
0344             pwr_val[i] = (u8)((writeval & (0x7f <<
0345                        (i * 8))) >> (i * 8));
0346 
0347             if (pwr_val[i] > RF6052_MAX_TX_PWR)
0348                 pwr_val[i] = RF6052_MAX_TX_PWR;
0349         }
0350         writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
0351             (pwr_val[1] << 8) | pwr_val[0];
0352 
0353         if (rf == 0)
0354             regoffset = regoffset_a[index];
0355         else
0356             regoffset = regoffset_b[index];
0357         rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);
0358 
0359         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0360             "Set 0x%x = %08x\n", regoffset, writeval);
0361     }
0362 }
0363 
0364 void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
0365                     u8 *ppowerlevel_ofdm,
0366                     u8 *ppowerlevel_bw20,
0367                     u8 *ppowerlevel_bw40, u8 channel)
0368 {
0369     u32 writeval[2], powerbase0[2], powerbase1[2];
0370     u8 index;
0371     u8 direction;
0372     u32 pwrtrac_value;
0373 
0374     rtl88e_phy_get_power_base(hw, ppowerlevel_ofdm,
0375                   ppowerlevel_bw20, ppowerlevel_bw40,
0376                   channel, &powerbase0[0], &powerbase1[0]);
0377 
0378     rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
0379 
0380     for (index = 0; index < 6; index++) {
0381         _rtl88e_get_txpower_writeval_by_regulatory(hw,
0382                                channel, index,
0383                                &powerbase0[0],
0384                                &powerbase1[0],
0385                                &writeval[0]);
0386         if (direction == 1) {
0387             writeval[0] += pwrtrac_value;
0388             writeval[1] += pwrtrac_value;
0389         } else if (direction == 2) {
0390             writeval[0] -= pwrtrac_value;
0391             writeval[1] -= pwrtrac_value;
0392         }
0393         _rtl88e_write_ofdm_power_reg(hw, index, &writeval[0]);
0394     }
0395 }
0396 
0397 bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw)
0398 {
0399     struct rtl_priv *rtlpriv = rtl_priv(hw);
0400     struct rtl_phy *rtlphy = &(rtlpriv->phy);
0401 
0402     if (rtlphy->rf_type == RF_1T1R)
0403         rtlphy->num_total_rfpath = 1;
0404     else
0405         rtlphy->num_total_rfpath = 2;
0406 
0407     return _rtl88e_phy_rf6052_config_parafile(hw);
0408 }
0409 
0410 static bool _rtl88e_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
0411 {
0412     struct rtl_priv *rtlpriv = rtl_priv(hw);
0413     struct rtl_phy *rtlphy = &rtlpriv->phy;
0414     u32 u4_regvalue = 0;
0415     u8 rfpath;
0416     bool rtstatus = true;
0417     struct bb_reg_def *pphyreg;
0418 
0419     for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
0420         pphyreg = &rtlphy->phyreg_def[rfpath];
0421 
0422         switch (rfpath) {
0423         case RF90_PATH_A:
0424         case RF90_PATH_C:
0425             u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
0426                             BRFSI_RFENV);
0427             break;
0428         case RF90_PATH_B:
0429         case RF90_PATH_D:
0430             u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
0431                             BRFSI_RFENV << 16);
0432             break;
0433         }
0434 
0435         rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
0436         udelay(1);
0437 
0438         rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
0439         udelay(1);
0440 
0441         rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
0442                   B3WIREADDREAALENGTH, 0x0);
0443         udelay(1);
0444 
0445         rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
0446         udelay(1);
0447 
0448         switch (rfpath) {
0449         case RF90_PATH_A:
0450             rtstatus = rtl88e_phy_config_rf_with_headerfile(hw,
0451                         (enum radio_path)rfpath);
0452             break;
0453         case RF90_PATH_B:
0454             rtstatus = rtl88e_phy_config_rf_with_headerfile(hw,
0455                         (enum radio_path)rfpath);
0456             break;
0457         case RF90_PATH_C:
0458             break;
0459         case RF90_PATH_D:
0460             break;
0461         }
0462 
0463         switch (rfpath) {
0464         case RF90_PATH_A:
0465         case RF90_PATH_C:
0466             rtl_set_bbreg(hw, pphyreg->rfintfs,
0467                       BRFSI_RFENV, u4_regvalue);
0468             break;
0469         case RF90_PATH_B:
0470         case RF90_PATH_D:
0471             rtl_set_bbreg(hw, pphyreg->rfintfs,
0472                       BRFSI_RFENV << 16, u4_regvalue);
0473             break;
0474         }
0475 
0476         if (!rtstatus) {
0477             rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
0478                 "Radio[%d] Fail!!\n", rfpath);
0479             return false;
0480         }
0481 
0482     }
0483 
0484     rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "\n");
0485     return rtstatus;
0486 }