121baa36dSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 28fc8598eSJerry Chuang /* 364b389c5SGavin Thomas Claugus * This is part of the rtl8192 driver 464b389c5SGavin Thomas Claugus * 564b389c5SGavin Thomas Claugus * This files contains programming code for the rtl8256 664b389c5SGavin Thomas Claugus * radio frontend. 764b389c5SGavin Thomas Claugus * 864b389c5SGavin Thomas Claugus * *Many* thanks to Realtek Corp. for their great support! 98fc8598eSJerry Chuang */ 108fc8598eSJerry Chuang 118fc8598eSJerry Chuang #include "r8192U.h" 128fc8598eSJerry Chuang #include "r8192U_hw.h" 138fc8598eSJerry Chuang #include "r819xU_phyreg.h" 148fc8598eSJerry Chuang #include "r819xU_phy.h" 158fc8598eSJerry Chuang #include "r8190_rtl8256.h" 168fc8598eSJerry Chuang 17319f9425SJohn Whitmore /* 18319f9425SJohn Whitmore * Forward declaration of local functions 19319f9425SJohn Whitmore */ 20319f9425SJohn Whitmore static void phy_rf8256_config_para_file(struct net_device *dev); 21319f9425SJohn Whitmore 228fc8598eSJerry Chuang /*-------------------------------------------------------------------------- 238fc8598eSJerry Chuang * Overview: set RF band width (20M or 40M) 248fc8598eSJerry Chuang * Input: struct net_device* dev 258fc8598eSJerry Chuang * WIRELESS_BANDWIDTH_E Bandwidth //20M or 40M 268fc8598eSJerry Chuang * Output: NONE 278fc8598eSJerry Chuang * Return: NONE 288fc8598eSJerry Chuang * Note: 8226 support both 20M and 40 MHz 2964b389c5SGavin Thomas Claugus *-------------------------------------------------------------------------- 3064b389c5SGavin Thomas Claugus */ 317c671608SJohn Whitmore void phy_set_rf8256_bandwidth(struct net_device *dev, enum ht_channel_width Bandwidth) 328fc8598eSJerry Chuang { 338fc8598eSJerry Chuang u8 eRFPath; 348fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 358fc8598eSJerry Chuang 36104cb5c0SSanjeev Sharma /* for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath; 37104cb5c0SSanjeev Sharma * eRFPath++) 38104cb5c0SSanjeev Sharma */ 39104cb5c0SSanjeev Sharma for (eRFPath = 0; eRFPath < RF90_PATH_MAX; eRFPath++) { 408fc8598eSJerry Chuang if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) 418fc8598eSJerry Chuang continue; 428fc8598eSJerry Chuang 43104cb5c0SSanjeev Sharma switch (Bandwidth) { 448fc8598eSJerry Chuang case HT_CHANNEL_WIDTH_20: 458c10170fSSumera Priyadarsini if (priv->card_8192_version == VERSION_819XU_A || 46d8a363efSSumera Priyadarsini priv->card_8192_version == VERSION_819XU_B) { 47d8a363efSSumera Priyadarsini /* 8256 D-cut, E-cut, xiong: consider it later! */ 48104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 49fb37edcfSJohn Whitmore (enum rf90_radio_path_e)eRFPath, 50104cb5c0SSanjeev Sharma 0x0b, bMask12Bits, 0x100); /* phy para:1ba */ 51104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 52fb37edcfSJohn Whitmore (enum rf90_radio_path_e)eRFPath, 53104cb5c0SSanjeev Sharma 0x2c, bMask12Bits, 0x3d7); 54104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 55fb37edcfSJohn Whitmore (enum rf90_radio_path_e)eRFPath, 56104cb5c0SSanjeev Sharma 0x0e, bMask12Bits, 0x021); 57104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 58fb37edcfSJohn Whitmore (enum rf90_radio_path_e)eRFPath, 59104cb5c0SSanjeev Sharma 0x14, bMask12Bits, 0x5ab); 60104cb5c0SSanjeev Sharma } else { 61*c6c4a17bSPuranjay Mohan RT_TRACE(COMP_ERR, "%s(): unknown hardware version\n", __func__); 628fc8598eSJerry Chuang } 638fc8598eSJerry Chuang break; 648fc8598eSJerry Chuang case HT_CHANNEL_WIDTH_20_40: 6564749a7eSJohn Whitmore if (priv->card_8192_version == VERSION_819XU_A || priv->card_8192_version == VERSION_819XU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */ 66fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0b, bMask12Bits, 0x300); /* phy para:3ba */ 67fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x2c, bMask12Bits, 0x3df); 68fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0e, bMask12Bits, 0x0a1); 698fc8598eSJerry Chuang 70104cb5c0SSanjeev Sharma if (priv->chan == 3 || priv->chan == 9) 7193a9f05aSSanjeev Sharma /* I need to set priv->chan whenever current channel changes */ 72fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x14, bMask12Bits, 0x59b); 738fc8598eSJerry Chuang else 74fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x14, bMask12Bits, 0x5ab); 75104cb5c0SSanjeev Sharma } else { 767c671608SJohn Whitmore RT_TRACE(COMP_ERR, "phy_set_rf8256_bandwidth(): unknown hardware version\n"); 778fc8598eSJerry Chuang } 788fc8598eSJerry Chuang break; 798fc8598eSJerry Chuang default: 807c671608SJohn Whitmore RT_TRACE(COMP_ERR, "phy_set_rf8256_bandwidth(): unknown Bandwidth: %#X\n", Bandwidth); 818fc8598eSJerry Chuang break; 8248d911f2SSumera Priyadarsini } 8348d911f2SSumera Priyadarsini } 8448d911f2SSumera Priyadarsini } 858fc8598eSJerry Chuang 868fc8598eSJerry Chuang /*-------------------------------------------------------------------------- 878fc8598eSJerry Chuang * Overview: Interface to config 8256 888fc8598eSJerry Chuang * Input: struct net_device* dev 898fc8598eSJerry Chuang * Output: NONE 908fc8598eSJerry Chuang * Return: NONE 9164b389c5SGavin Thomas Claugus *-------------------------------------------------------------------------- 9264b389c5SGavin Thomas Claugus */ 939980fd11SJohn Whitmore void phy_rf8256_config(struct net_device *dev) 948fc8598eSJerry Chuang { 958fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 9693a9f05aSSanjeev Sharma /* Initialize general global value 9793a9f05aSSanjeev Sharma * 9893a9f05aSSanjeev Sharma * TODO: Extend RF_PATH_C and RF_PATH_D in the future 9993a9f05aSSanjeev Sharma */ 1008fc8598eSJerry Chuang priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH; 10193a9f05aSSanjeev Sharma /* Config BB and RF */ 102319f9425SJohn Whitmore phy_rf8256_config_para_file(dev); 1038fc8598eSJerry Chuang } 10448d911f2SSumera Priyadarsini 1058fc8598eSJerry Chuang /*-------------------------------------------------------------------------- 1068fc8598eSJerry Chuang * Overview: Interface to config 8256 1078fc8598eSJerry Chuang * Input: struct net_device* dev 1088fc8598eSJerry Chuang * Output: NONE 1098fc8598eSJerry Chuang * Return: NONE 11064b389c5SGavin Thomas Claugus *-------------------------------------------------------------------------- 11164b389c5SGavin Thomas Claugus */ 112319f9425SJohn Whitmore static void phy_rf8256_config_para_file(struct net_device *dev) 1138fc8598eSJerry Chuang { 1148fc8598eSJerry Chuang u32 u4RegValue = 0; 1158fc8598eSJerry Chuang u8 eRFPath; 1168fc8598eSJerry Chuang BB_REGISTER_DEFINITION_T *pPhyReg; 1178fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 1188fc8598eSJerry Chuang u32 RegOffSetToBeCheck = 0x3; 1198fc8598eSJerry Chuang u32 RegValueToBeCheck = 0x7f1; 1208fc8598eSJerry Chuang u32 RF3_Final_Value = 0; 1218fc8598eSJerry Chuang u8 ConstRetryTimes = 5, RetryTimes = 5; 1228fc8598eSJerry Chuang u8 ret = 0; 12393a9f05aSSanjeev Sharma /* Initialize RF */ 124fb37edcfSJohn Whitmore for (eRFPath = (enum rf90_radio_path_e)RF90_PATH_A; eRFPath < priv->NumTotalRFPath; eRFPath++) { 1258fc8598eSJerry Chuang if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) 1268fc8598eSJerry Chuang continue; 1278fc8598eSJerry Chuang 1288fc8598eSJerry Chuang pPhyReg = &priv->PHYRegDef[eRFPath]; 1298fc8598eSJerry Chuang 13093a9f05aSSanjeev Sharma /* Joseph test for shorten RF config 131fb37edcfSJohn Whitmore * pHalData->RfReg0Value[eRFPath] = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, rGlobalCtrl, bMaskDWord); 13293a9f05aSSanjeev Sharma * ----Store original RFENV control type 13393a9f05aSSanjeev Sharma */ 134104cb5c0SSanjeev Sharma switch (eRFPath) { 1358fc8598eSJerry Chuang case RF90_PATH_A: 1368fc8598eSJerry Chuang case RF90_PATH_C: 1378fc8598eSJerry Chuang u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV); 1388fc8598eSJerry Chuang break; 1398fc8598eSJerry Chuang case RF90_PATH_B: 1408fc8598eSJerry Chuang case RF90_PATH_D: 1418fc8598eSJerry Chuang u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV << 16); 1428fc8598eSJerry Chuang break; 1438fc8598eSJerry Chuang } 1448fc8598eSJerry Chuang 1458fc8598eSJerry Chuang /*----Set RF_ENV enable----*/ 1468fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); 1478fc8598eSJerry Chuang 1488fc8598eSJerry Chuang /*----Set RF_ENV output high----*/ 1498fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); 1508fc8598eSJerry Chuang 1518fc8598eSJerry Chuang /* Set bit number of Address and Data for RF register */ 15293a9f05aSSanjeev Sharma rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258 */ 15393a9f05aSSanjeev Sharma rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ??? */ 1548fc8598eSJerry Chuang 155fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0, bMask12Bits, 0xbf); 1568fc8598eSJerry Chuang 15793a9f05aSSanjeev Sharma /* Check RF block (for FPGA platform only)---- 15893a9f05aSSanjeev Sharma * TODO: this function should be removed on ASIC , Emily 2007.2.2 15993a9f05aSSanjeev Sharma */ 160fb37edcfSJohn Whitmore if (rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, (enum rf90_radio_path_e)eRFPath)) { 1619980fd11SJohn Whitmore RT_TRACE(COMP_ERR, "phy_rf8256_config():Check Radio[%d] Fail!!\n", eRFPath); 1628fc8598eSJerry Chuang goto phy_RF8256_Config_ParaFile_Fail; 1638fc8598eSJerry Chuang } 1648fc8598eSJerry Chuang 1658fc8598eSJerry Chuang RetryTimes = ConstRetryTimes; 1668fc8598eSJerry Chuang RF3_Final_Value = 0; 1678fc8598eSJerry Chuang /*----Initialize RF fom connfiguration file----*/ 168104cb5c0SSanjeev Sharma switch (eRFPath) { 1698fc8598eSJerry Chuang case RF90_PATH_A: 170104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 171fb37edcfSJohn Whitmore ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath); 172fb37edcfSJohn Whitmore RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits); 1738fc8598eSJerry Chuang RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); 1748fc8598eSJerry Chuang RetryTimes--; 1758fc8598eSJerry Chuang } 1768fc8598eSJerry Chuang break; 1778fc8598eSJerry Chuang case RF90_PATH_B: 178104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 179fb37edcfSJohn Whitmore ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath); 180fb37edcfSJohn Whitmore RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits); 1818fc8598eSJerry Chuang RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); 1828fc8598eSJerry Chuang RetryTimes--; 1838fc8598eSJerry Chuang } 1848fc8598eSJerry Chuang break; 1858fc8598eSJerry Chuang case RF90_PATH_C: 186104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 187fb37edcfSJohn Whitmore ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath); 188fb37edcfSJohn Whitmore RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits); 1898fc8598eSJerry Chuang RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); 1908fc8598eSJerry Chuang RetryTimes--; 1918fc8598eSJerry Chuang } 1928fc8598eSJerry Chuang break; 1938fc8598eSJerry Chuang case RF90_PATH_D: 194104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 195fb37edcfSJohn Whitmore ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath); 196fb37edcfSJohn Whitmore RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits); 1978fc8598eSJerry Chuang RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); 1988fc8598eSJerry Chuang RetryTimes--; 1998fc8598eSJerry Chuang } 2008fc8598eSJerry Chuang break; 2018fc8598eSJerry Chuang } 2028fc8598eSJerry Chuang 20346347b3eSSandhya Bankar /*----Restore RFENV control type----*/ 204104cb5c0SSanjeev Sharma switch (eRFPath) { 2058fc8598eSJerry Chuang case RF90_PATH_A: 2068fc8598eSJerry Chuang case RF90_PATH_C: 2078fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue); 2088fc8598eSJerry Chuang break; 2098fc8598eSJerry Chuang case RF90_PATH_B: 2108fc8598eSJerry Chuang case RF90_PATH_D: 2118fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue); 2128fc8598eSJerry Chuang break; 2138fc8598eSJerry Chuang } 2148fc8598eSJerry Chuang 2158fc8598eSJerry Chuang if (ret) { 216319f9425SJohn Whitmore RT_TRACE(COMP_ERR, "phy_rf8256_config_para_file():Radio[%d] Fail!!", eRFPath); 2178fc8598eSJerry Chuang goto phy_RF8256_Config_ParaFile_Fail; 2188fc8598eSJerry Chuang } 2198fc8598eSJerry Chuang } 2208fc8598eSJerry Chuang 2218fc8598eSJerry Chuang RT_TRACE(COMP_PHY, "PHY Initialization Success\n"); 2228fc8598eSJerry Chuang return; 2238fc8598eSJerry Chuang 2248fc8598eSJerry Chuang phy_RF8256_Config_ParaFile_Fail: 2258fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "PHY Initialization failed\n"); 2268fc8598eSJerry Chuang } 2278fc8598eSJerry Chuang 2283942039aSJohn Whitmore void phy_set_rf8256_cck_tx_power(struct net_device *dev, u8 powerlevel) 2298fc8598eSJerry Chuang { 2308fc8598eSJerry Chuang u32 TxAGC = 0; 2318fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 23248d911f2SSumera Priyadarsini 2338fc8598eSJerry Chuang TxAGC = powerlevel; 2348fc8598eSJerry Chuang 23572b16fe3SKsenija Stanojevic if (priv->bDynamicTxLowPower) { 2368fc8598eSJerry Chuang if (priv->CustomerID == RT_CID_819x_Netcore) 2378fc8598eSJerry Chuang TxAGC = 0x22; 2388fc8598eSJerry Chuang else 2398fc8598eSJerry Chuang TxAGC += priv->CckPwEnl; 2408fc8598eSJerry Chuang } 2418fc8598eSJerry Chuang 2428fc8598eSJerry Chuang if (TxAGC > 0x24) 2438fc8598eSJerry Chuang TxAGC = 0x24; 2448fc8598eSJerry Chuang rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); 2458fc8598eSJerry Chuang } 2468fc8598eSJerry Chuang 247071327fcSJohn Whitmore void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) 2488fc8598eSJerry Chuang { 2498fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 25093a9f05aSSanjeev Sharma /* Joseph TxPower for 8192 testing */ 2518fc8598eSJerry Chuang u32 writeVal, powerBase0, powerBase1, writeVal_tmp; 2528fc8598eSJerry Chuang u8 index = 0; 2538fc8598eSJerry Chuang u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; 2548fc8598eSJerry Chuang u8 byte0, byte1, byte2, byte3; 2558fc8598eSJerry Chuang 25693a9f05aSSanjeev Sharma powerBase0 = powerlevel + priv->TxPowerDiff; /* OFDM rates */ 2578fc8598eSJerry Chuang powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | (powerBase0 << 8) | powerBase0; 25893a9f05aSSanjeev Sharma powerBase1 = powerlevel; /* MCS rates */ 2598fc8598eSJerry Chuang powerBase1 = (powerBase1 << 24) | (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; 2608fc8598eSJerry Chuang 261104cb5c0SSanjeev Sharma for (index = 0; index < 6; index++) { 2628fc8598eSJerry Chuang writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index < 2) ? powerBase0 : powerBase1); 2638fc8598eSJerry Chuang byte0 = (u8)(writeVal & 0x7f); 2648fc8598eSJerry Chuang byte1 = (u8)((writeVal & 0x7f00) >> 8); 2658fc8598eSJerry Chuang byte2 = (u8)((writeVal & 0x7f0000) >> 16); 2668fc8598eSJerry Chuang byte3 = (u8)((writeVal & 0x7f000000) >> 24); 267104cb5c0SSanjeev Sharma 268104cb5c0SSanjeev Sharma if (byte0 > 0x24) 269104cb5c0SSanjeev Sharma /* Max power index = 0x24 */ 2708fc8598eSJerry Chuang byte0 = 0x24; 2718fc8598eSJerry Chuang if (byte1 > 0x24) 2728fc8598eSJerry Chuang byte1 = 0x24; 2738fc8598eSJerry Chuang if (byte2 > 0x24) 2748fc8598eSJerry Chuang byte2 = 0x24; 2758fc8598eSJerry Chuang if (byte3 > 0x24) 2768fc8598eSJerry Chuang byte3 = 0x24; 2778fc8598eSJerry Chuang 27893a9f05aSSanjeev Sharma /* for tx power track */ 279104cb5c0SSanjeev Sharma if (index == 3) { 2808fc8598eSJerry Chuang writeVal_tmp = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0; 2818fc8598eSJerry Chuang priv->Pwr_Track = writeVal_tmp; 2828fc8598eSJerry Chuang } 2838fc8598eSJerry Chuang 28472b16fe3SKsenija Stanojevic if (priv->bDynamicTxHighPower) { 285104cb5c0SSanjeev Sharma /*Add by Jacken 2008/03/06 286104cb5c0SSanjeev Sharma *Emily, 20080613. Set low tx power for both MCS and legacy OFDM 287104cb5c0SSanjeev Sharma */ 2888fc8598eSJerry Chuang writeVal = 0x03030303; 289104cb5c0SSanjeev Sharma } else { 2908fc8598eSJerry Chuang writeVal = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0; 2918fc8598eSJerry Chuang } 2928fc8598eSJerry Chuang rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); 2938fc8598eSJerry Chuang } 2948fc8598eSJerry Chuang return; 2958fc8598eSJerry Chuang } 296