linux/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c
<<
>>
Prefs
   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 _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
  12
  13void 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
  37void 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
 124static 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
 165static 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
 306static 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
 371void 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
 391bool 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
 405static 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                        rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
 474                                "Radio[%d] Fail!!\n", rfpath);
 475                        return false;
 476                }
 477
 478        }
 479
 480        rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");
 481        return rtstatus;
 482}
 483