18fc8598eSJerry Chuang /* 264b389c5SGavin Thomas Claugus * This is part of the rtl8192 driver 364b389c5SGavin Thomas Claugus * released under the GPL (See file COPYING for details). 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 178fc8598eSJerry Chuang /*-------------------------------------------------------------------------- 188fc8598eSJerry Chuang * Overview: set RF band width (20M or 40M) 198fc8598eSJerry Chuang * Input: struct net_device* dev 208fc8598eSJerry Chuang * WIRELESS_BANDWIDTH_E Bandwidth //20M or 40M 218fc8598eSJerry Chuang * Output: NONE 228fc8598eSJerry Chuang * Return: NONE 238fc8598eSJerry Chuang * Note: 8226 support both 20M and 40 MHz 2464b389c5SGavin Thomas Claugus *-------------------------------------------------------------------------- 2564b389c5SGavin Thomas Claugus */ 2685472724SJohn Whitmore void PHY_SetRF8256Bandwidth(struct net_device *dev, enum ht_channel_width Bandwidth) 278fc8598eSJerry Chuang { 288fc8598eSJerry Chuang u8 eRFPath; 298fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 308fc8598eSJerry Chuang 31104cb5c0SSanjeev Sharma /* for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath; 32104cb5c0SSanjeev Sharma * eRFPath++) 33104cb5c0SSanjeev Sharma */ 34104cb5c0SSanjeev Sharma for (eRFPath = 0; eRFPath < RF90_PATH_MAX; eRFPath++) { 358fc8598eSJerry Chuang if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) 368fc8598eSJerry Chuang continue; 378fc8598eSJerry Chuang 38104cb5c0SSanjeev Sharma switch (Bandwidth) { 398fc8598eSJerry Chuang case HT_CHANNEL_WIDTH_20: 4064749a7eSJohn Whitmore if (priv->card_8192_version == VERSION_819XU_A 41104cb5c0SSanjeev Sharma || priv->card_8192_version 4264749a7eSJohn Whitmore == VERSION_819XU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */ 43104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 44fb37edcfSJohn Whitmore (enum rf90_radio_path_e)eRFPath, 45104cb5c0SSanjeev Sharma 0x0b, bMask12Bits, 0x100); /* phy para:1ba */ 46104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 47fb37edcfSJohn Whitmore (enum rf90_radio_path_e)eRFPath, 48104cb5c0SSanjeev Sharma 0x2c, bMask12Bits, 0x3d7); 49104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 50fb37edcfSJohn Whitmore (enum rf90_radio_path_e)eRFPath, 51104cb5c0SSanjeev Sharma 0x0e, bMask12Bits, 0x021); 52104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 53fb37edcfSJohn Whitmore (enum rf90_radio_path_e)eRFPath, 54104cb5c0SSanjeev Sharma 0x14, bMask12Bits, 0x5ab); 55104cb5c0SSanjeev Sharma } else { 568fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n"); 578fc8598eSJerry Chuang } 588fc8598eSJerry Chuang break; 598fc8598eSJerry Chuang case HT_CHANNEL_WIDTH_20_40: 6064749a7eSJohn 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! */ 61fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0b, bMask12Bits, 0x300); /* phy para:3ba */ 62fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x2c, bMask12Bits, 0x3df); 63fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0e, bMask12Bits, 0x0a1); 648fc8598eSJerry Chuang 65104cb5c0SSanjeev Sharma if (priv->chan == 3 || priv->chan == 9) 6693a9f05aSSanjeev Sharma /* I need to set priv->chan whenever current channel changes */ 67fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x14, bMask12Bits, 0x59b); 688fc8598eSJerry Chuang else 69fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x14, bMask12Bits, 0x5ab); 70104cb5c0SSanjeev Sharma } else { 718fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n"); 728fc8598eSJerry Chuang } 738fc8598eSJerry Chuang break; 748fc8598eSJerry Chuang default: 758fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n", Bandwidth); 768fc8598eSJerry Chuang break; 778fc8598eSJerry Chuang 788fc8598eSJerry Chuang } 798fc8598eSJerry Chuang } 808fc8598eSJerry Chuang } 818fc8598eSJerry Chuang /*-------------------------------------------------------------------------- 828fc8598eSJerry Chuang * Overview: Interface to config 8256 838fc8598eSJerry Chuang * Input: struct net_device* dev 848fc8598eSJerry Chuang * Output: NONE 858fc8598eSJerry Chuang * Return: NONE 8664b389c5SGavin Thomas Claugus *-------------------------------------------------------------------------- 8764b389c5SGavin Thomas Claugus */ 888fc8598eSJerry Chuang void PHY_RF8256_Config(struct net_device *dev) 898fc8598eSJerry Chuang { 908fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 9193a9f05aSSanjeev Sharma /* Initialize general global value 9293a9f05aSSanjeev Sharma * 9393a9f05aSSanjeev Sharma * TODO: Extend RF_PATH_C and RF_PATH_D in the future 9493a9f05aSSanjeev Sharma */ 958fc8598eSJerry Chuang priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH; 9693a9f05aSSanjeev Sharma /* Config BB and RF */ 978fc8598eSJerry Chuang phy_RF8256_Config_ParaFile(dev); 988fc8598eSJerry Chuang } 998fc8598eSJerry Chuang /*-------------------------------------------------------------------------- 1008fc8598eSJerry Chuang * Overview: Interface to config 8256 1018fc8598eSJerry Chuang * Input: struct net_device* dev 1028fc8598eSJerry Chuang * Output: NONE 1038fc8598eSJerry Chuang * Return: NONE 10464b389c5SGavin Thomas Claugus *-------------------------------------------------------------------------- 10564b389c5SGavin Thomas Claugus */ 1068fc8598eSJerry Chuang void phy_RF8256_Config_ParaFile(struct net_device *dev) 1078fc8598eSJerry Chuang { 1088fc8598eSJerry Chuang u32 u4RegValue = 0; 1098fc8598eSJerry Chuang u8 eRFPath; 1108fc8598eSJerry Chuang BB_REGISTER_DEFINITION_T *pPhyReg; 1118fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 1128fc8598eSJerry Chuang u32 RegOffSetToBeCheck = 0x3; 1138fc8598eSJerry Chuang u32 RegValueToBeCheck = 0x7f1; 1148fc8598eSJerry Chuang u32 RF3_Final_Value = 0; 1158fc8598eSJerry Chuang u8 ConstRetryTimes = 5, RetryTimes = 5; 1168fc8598eSJerry Chuang u8 ret = 0; 11793a9f05aSSanjeev Sharma /* Initialize RF */ 118fb37edcfSJohn Whitmore for (eRFPath = (enum rf90_radio_path_e)RF90_PATH_A; eRFPath < priv->NumTotalRFPath; eRFPath++) { 1198fc8598eSJerry Chuang if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) 1208fc8598eSJerry Chuang continue; 1218fc8598eSJerry Chuang 1228fc8598eSJerry Chuang pPhyReg = &priv->PHYRegDef[eRFPath]; 1238fc8598eSJerry Chuang 12493a9f05aSSanjeev Sharma /* Joseph test for shorten RF config 125fb37edcfSJohn Whitmore * pHalData->RfReg0Value[eRFPath] = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, rGlobalCtrl, bMaskDWord); 12693a9f05aSSanjeev Sharma * ----Store original RFENV control type 12793a9f05aSSanjeev Sharma */ 128104cb5c0SSanjeev Sharma switch (eRFPath) { 1298fc8598eSJerry Chuang case RF90_PATH_A: 1308fc8598eSJerry Chuang case RF90_PATH_C: 1318fc8598eSJerry Chuang u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV); 1328fc8598eSJerry Chuang break; 1338fc8598eSJerry Chuang case RF90_PATH_B: 1348fc8598eSJerry Chuang case RF90_PATH_D: 1358fc8598eSJerry Chuang u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16); 1368fc8598eSJerry Chuang break; 1378fc8598eSJerry Chuang } 1388fc8598eSJerry Chuang 1398fc8598eSJerry Chuang /*----Set RF_ENV enable----*/ 1408fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1); 1418fc8598eSJerry Chuang 1428fc8598eSJerry Chuang /*----Set RF_ENV output high----*/ 1438fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); 1448fc8598eSJerry Chuang 1458fc8598eSJerry Chuang /* Set bit number of Address and Data for RF register */ 14693a9f05aSSanjeev Sharma rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258 */ 14793a9f05aSSanjeev 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 ??? */ 1488fc8598eSJerry Chuang 149fb37edcfSJohn Whitmore rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e) eRFPath, 0x0, bMask12Bits, 0xbf); 1508fc8598eSJerry Chuang 15193a9f05aSSanjeev Sharma /* Check RF block (for FPGA platform only)---- 15293a9f05aSSanjeev Sharma * TODO: this function should be removed on ASIC , Emily 2007.2.2 15393a9f05aSSanjeev Sharma */ 154fb37edcfSJohn Whitmore if (rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, (enum rf90_radio_path_e)eRFPath)) { 1558fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check Radio[%d] Fail!!\n", eRFPath); 1568fc8598eSJerry Chuang goto phy_RF8256_Config_ParaFile_Fail; 1578fc8598eSJerry Chuang } 1588fc8598eSJerry Chuang 1598fc8598eSJerry Chuang RetryTimes = ConstRetryTimes; 1608fc8598eSJerry Chuang RF3_Final_Value = 0; 1618fc8598eSJerry Chuang /*----Initialize RF fom connfiguration file----*/ 162104cb5c0SSanjeev Sharma switch (eRFPath) { 1638fc8598eSJerry Chuang case RF90_PATH_A: 164104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 165fb37edcfSJohn Whitmore ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath); 166fb37edcfSJohn Whitmore RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits); 1678fc8598eSJerry Chuang RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); 1688fc8598eSJerry Chuang RetryTimes--; 1698fc8598eSJerry Chuang } 1708fc8598eSJerry Chuang break; 1718fc8598eSJerry Chuang case RF90_PATH_B: 172104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 173fb37edcfSJohn Whitmore ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath); 174fb37edcfSJohn Whitmore RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits); 1758fc8598eSJerry Chuang RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); 1768fc8598eSJerry Chuang RetryTimes--; 1778fc8598eSJerry Chuang } 1788fc8598eSJerry Chuang break; 1798fc8598eSJerry Chuang case RF90_PATH_C: 180104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 181fb37edcfSJohn Whitmore ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath); 182fb37edcfSJohn Whitmore RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits); 1838fc8598eSJerry Chuang RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); 1848fc8598eSJerry Chuang RetryTimes--; 1858fc8598eSJerry Chuang } 1868fc8598eSJerry Chuang break; 1878fc8598eSJerry Chuang case RF90_PATH_D: 188104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 189fb37edcfSJohn Whitmore ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath); 190fb37edcfSJohn Whitmore RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits); 1918fc8598eSJerry Chuang RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); 1928fc8598eSJerry Chuang RetryTimes--; 1938fc8598eSJerry Chuang } 1948fc8598eSJerry Chuang break; 1958fc8598eSJerry Chuang } 1968fc8598eSJerry Chuang 19746347b3eSSandhya Bankar /*----Restore RFENV control type----*/ 198104cb5c0SSanjeev Sharma switch (eRFPath) { 1998fc8598eSJerry Chuang case RF90_PATH_A: 2008fc8598eSJerry Chuang case RF90_PATH_C: 2018fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue); 2028fc8598eSJerry Chuang break; 2038fc8598eSJerry Chuang case RF90_PATH_B: 2048fc8598eSJerry Chuang case RF90_PATH_D: 2058fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue); 2068fc8598eSJerry Chuang break; 2078fc8598eSJerry Chuang } 2088fc8598eSJerry Chuang 2098fc8598eSJerry Chuang if (ret) { 2108fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!", eRFPath); 2118fc8598eSJerry Chuang goto phy_RF8256_Config_ParaFile_Fail; 2128fc8598eSJerry Chuang } 2138fc8598eSJerry Chuang 2148fc8598eSJerry Chuang } 2158fc8598eSJerry Chuang 2168fc8598eSJerry Chuang RT_TRACE(COMP_PHY, "PHY Initialization Success\n"); 2178fc8598eSJerry Chuang return; 2188fc8598eSJerry Chuang 2198fc8598eSJerry Chuang phy_RF8256_Config_ParaFile_Fail: 2208fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "PHY Initialization failed\n"); 2218fc8598eSJerry Chuang } 2228fc8598eSJerry Chuang 2238fc8598eSJerry Chuang 2248fc8598eSJerry Chuang void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel) 2258fc8598eSJerry Chuang { 2268fc8598eSJerry Chuang u32 TxAGC = 0; 2278fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 2288fc8598eSJerry Chuang TxAGC = powerlevel; 2298fc8598eSJerry Chuang 23072b16fe3SKsenija Stanojevic if (priv->bDynamicTxLowPower) { 2318fc8598eSJerry Chuang if (priv->CustomerID == RT_CID_819x_Netcore) 2328fc8598eSJerry Chuang TxAGC = 0x22; 2338fc8598eSJerry Chuang else 2348fc8598eSJerry Chuang TxAGC += priv->CckPwEnl; 2358fc8598eSJerry Chuang } 2368fc8598eSJerry Chuang 2378fc8598eSJerry Chuang if (TxAGC > 0x24) 2388fc8598eSJerry Chuang TxAGC = 0x24; 2398fc8598eSJerry Chuang rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); 2408fc8598eSJerry Chuang } 2418fc8598eSJerry Chuang 2428fc8598eSJerry Chuang 2438fc8598eSJerry Chuang void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel) 2448fc8598eSJerry Chuang { 2458fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 24693a9f05aSSanjeev Sharma /* Joseph TxPower for 8192 testing */ 2478fc8598eSJerry Chuang u32 writeVal, powerBase0, powerBase1, writeVal_tmp; 2488fc8598eSJerry Chuang u8 index = 0; 2498fc8598eSJerry Chuang u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; 2508fc8598eSJerry Chuang u8 byte0, byte1, byte2, byte3; 2518fc8598eSJerry Chuang 25293a9f05aSSanjeev Sharma powerBase0 = powerlevel + priv->TxPowerDiff; /* OFDM rates */ 2538fc8598eSJerry Chuang powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0; 25493a9f05aSSanjeev Sharma powerBase1 = powerlevel; /* MCS rates */ 2558fc8598eSJerry Chuang powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1; 2568fc8598eSJerry Chuang 257104cb5c0SSanjeev Sharma for (index = 0; index < 6; index++) { 2588fc8598eSJerry Chuang writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index < 2)?powerBase0:powerBase1); 2598fc8598eSJerry Chuang byte0 = (u8)(writeVal & 0x7f); 2608fc8598eSJerry Chuang byte1 = (u8)((writeVal & 0x7f00)>>8); 2618fc8598eSJerry Chuang byte2 = (u8)((writeVal & 0x7f0000)>>16); 2628fc8598eSJerry Chuang byte3 = (u8)((writeVal & 0x7f000000)>>24); 263104cb5c0SSanjeev Sharma 264104cb5c0SSanjeev Sharma if (byte0 > 0x24) 265104cb5c0SSanjeev Sharma /* Max power index = 0x24 */ 2668fc8598eSJerry Chuang byte0 = 0x24; 2678fc8598eSJerry Chuang if (byte1 > 0x24) 2688fc8598eSJerry Chuang byte1 = 0x24; 2698fc8598eSJerry Chuang if (byte2 > 0x24) 2708fc8598eSJerry Chuang byte2 = 0x24; 2718fc8598eSJerry Chuang if (byte3 > 0x24) 2728fc8598eSJerry Chuang byte3 = 0x24; 2738fc8598eSJerry Chuang 27493a9f05aSSanjeev Sharma /* for tx power track */ 275104cb5c0SSanjeev Sharma if (index == 3) { 2768fc8598eSJerry Chuang writeVal_tmp = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0; 2778fc8598eSJerry Chuang priv->Pwr_Track = writeVal_tmp; 2788fc8598eSJerry Chuang } 2798fc8598eSJerry Chuang 28072b16fe3SKsenija Stanojevic if (priv->bDynamicTxHighPower) { 281104cb5c0SSanjeev Sharma /*Add by Jacken 2008/03/06 282104cb5c0SSanjeev Sharma *Emily, 20080613. Set low tx power for both MCS and legacy OFDM 283104cb5c0SSanjeev Sharma */ 2848fc8598eSJerry Chuang writeVal = 0x03030303; 285104cb5c0SSanjeev Sharma } else { 2868fc8598eSJerry Chuang writeVal = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0; 2878fc8598eSJerry Chuang } 2888fc8598eSJerry Chuang rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); 2898fc8598eSJerry Chuang } 2908fc8598eSJerry Chuang return; 2918fc8598eSJerry Chuang 2928fc8598eSJerry Chuang } 293