18fc8598eSJerry Chuang /* 28fc8598eSJerry Chuang This is part of the rtl8192 driver 38fc8598eSJerry Chuang released under the GPL (See file COPYING for details). 48fc8598eSJerry Chuang 58fc8598eSJerry Chuang This files contains programming code for the rtl8256 68fc8598eSJerry Chuang radio frontend. 78fc8598eSJerry Chuang 88fc8598eSJerry Chuang *Many* thanks to Realtek Corp. for their great support! 98fc8598eSJerry Chuang 108fc8598eSJerry Chuang */ 118fc8598eSJerry Chuang 128fc8598eSJerry Chuang #include "r8192U.h" 138fc8598eSJerry Chuang #include "r8192U_hw.h" 148fc8598eSJerry Chuang #include "r819xU_phyreg.h" 158fc8598eSJerry Chuang #include "r819xU_phy.h" 168fc8598eSJerry Chuang #include "r8190_rtl8256.h" 178fc8598eSJerry Chuang 188fc8598eSJerry Chuang /*-------------------------------------------------------------------------- 198fc8598eSJerry Chuang * Overview: set RF band width (20M or 40M) 208fc8598eSJerry Chuang * Input: struct net_device* dev 218fc8598eSJerry Chuang * WIRELESS_BANDWIDTH_E Bandwidth //20M or 40M 228fc8598eSJerry Chuang * Output: NONE 238fc8598eSJerry Chuang * Return: NONE 248fc8598eSJerry Chuang * Note: 8226 support both 20M and 40 MHz 258fc8598eSJerry Chuang *---------------------------------------------------------------------------*/ 26104cb5c0SSanjeev Sharma void PHY_SetRF8256Bandwidth(struct net_device *dev , 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: 40104cb5c0SSanjeev Sharma if (priv->card_8192_version == VERSION_819xU_A 41104cb5c0SSanjeev Sharma || priv->card_8192_version 42104cb5c0SSanjeev Sharma == VERSION_819xU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */ 43104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 44104cb5c0SSanjeev Sharma (RF90_RADIO_PATH_E)eRFPath, 45104cb5c0SSanjeev Sharma 0x0b, bMask12Bits, 0x100); /* phy para:1ba */ 46104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 47104cb5c0SSanjeev Sharma (RF90_RADIO_PATH_E)eRFPath, 48104cb5c0SSanjeev Sharma 0x2c, bMask12Bits, 0x3d7); 49104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 50104cb5c0SSanjeev Sharma (RF90_RADIO_PATH_E)eRFPath, 51104cb5c0SSanjeev Sharma 0x0e, bMask12Bits, 0x021); 52104cb5c0SSanjeev Sharma rtl8192_phy_SetRFReg(dev, 53104cb5c0SSanjeev Sharma (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: 60104cb5c0SSanjeev Sharma if (priv->card_8192_version == VERSION_819xU_A || priv->card_8192_version == VERSION_819xU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */ 6193a9f05aSSanjeev Sharma rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x300); /* phy para:3ba */ 628fc8598eSJerry Chuang rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3df); 638fc8598eSJerry Chuang rtl8192_phy_SetRFReg(dev, (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 */ 678fc8598eSJerry Chuang rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x59b); 688fc8598eSJerry Chuang else 698fc8598eSJerry Chuang rtl8192_phy_SetRFReg(dev, (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 868fc8598eSJerry Chuang *---------------------------------------------------------------------------*/ 878fc8598eSJerry Chuang void PHY_RF8256_Config(struct net_device *dev) 888fc8598eSJerry Chuang { 898fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 9093a9f05aSSanjeev Sharma /* Initialize general global value 9193a9f05aSSanjeev Sharma * 9293a9f05aSSanjeev Sharma * TODO: Extend RF_PATH_C and RF_PATH_D in the future 9393a9f05aSSanjeev Sharma */ 948fc8598eSJerry Chuang priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH; 9593a9f05aSSanjeev Sharma /* Config BB and RF */ 968fc8598eSJerry Chuang phy_RF8256_Config_ParaFile(dev); 978fc8598eSJerry Chuang } 988fc8598eSJerry Chuang /*-------------------------------------------------------------------------- 998fc8598eSJerry Chuang * Overview: Interface to config 8256 1008fc8598eSJerry Chuang * Input: struct net_device* dev 1018fc8598eSJerry Chuang * Output: NONE 1028fc8598eSJerry Chuang * Return: NONE 1038fc8598eSJerry Chuang *---------------------------------------------------------------------------*/ 1048fc8598eSJerry Chuang void phy_RF8256_Config_ParaFile(struct net_device *dev) 1058fc8598eSJerry Chuang { 1068fc8598eSJerry Chuang u32 u4RegValue = 0; 1078fc8598eSJerry Chuang u8 eRFPath; 1088fc8598eSJerry Chuang BB_REGISTER_DEFINITION_T *pPhyReg; 1098fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 1108fc8598eSJerry Chuang u32 RegOffSetToBeCheck = 0x3; 1118fc8598eSJerry Chuang u32 RegValueToBeCheck = 0x7f1; 1128fc8598eSJerry Chuang u32 RF3_Final_Value = 0; 1138fc8598eSJerry Chuang u8 ConstRetryTimes = 5, RetryTimes = 5; 1148fc8598eSJerry Chuang u8 ret = 0; 11593a9f05aSSanjeev Sharma /* Initialize RF */ 116104cb5c0SSanjeev Sharma for (eRFPath = (RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath < priv->NumTotalRFPath; eRFPath++) { 1178fc8598eSJerry Chuang if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) 1188fc8598eSJerry Chuang continue; 1198fc8598eSJerry Chuang 1208fc8598eSJerry Chuang pPhyReg = &priv->PHYRegDef[eRFPath]; 1218fc8598eSJerry Chuang 12293a9f05aSSanjeev Sharma /* Joseph test for shorten RF config 12393a9f05aSSanjeev Sharma * pHalData->RfReg0Value[eRFPath] = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rGlobalCtrl, bMaskDWord); 12493a9f05aSSanjeev Sharma * ----Store original RFENV control type 12593a9f05aSSanjeev Sharma */ 126104cb5c0SSanjeev Sharma switch (eRFPath) { 1278fc8598eSJerry Chuang case RF90_PATH_A: 1288fc8598eSJerry Chuang case RF90_PATH_C: 1298fc8598eSJerry Chuang u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV); 1308fc8598eSJerry Chuang break; 1318fc8598eSJerry Chuang case RF90_PATH_B: 1328fc8598eSJerry Chuang case RF90_PATH_D: 1338fc8598eSJerry Chuang u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16); 1348fc8598eSJerry Chuang break; 1358fc8598eSJerry Chuang } 1368fc8598eSJerry Chuang 1378fc8598eSJerry Chuang /*----Set RF_ENV enable----*/ 1388fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1); 1398fc8598eSJerry Chuang 1408fc8598eSJerry Chuang /*----Set RF_ENV output high----*/ 1418fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); 1428fc8598eSJerry Chuang 1438fc8598eSJerry Chuang /* Set bit number of Address and Data for RF register */ 14493a9f05aSSanjeev Sharma rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258 */ 14593a9f05aSSanjeev 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 ??? */ 1468fc8598eSJerry Chuang 1478fc8598eSJerry Chuang rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E) eRFPath, 0x0, bMask12Bits, 0xbf); 1488fc8598eSJerry Chuang 14993a9f05aSSanjeev Sharma /* Check RF block (for FPGA platform only)---- 15093a9f05aSSanjeev Sharma * TODO: this function should be removed on ASIC , Emily 2007.2.2 15193a9f05aSSanjeev Sharma */ 152104cb5c0SSanjeev Sharma if (rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, (RF90_RADIO_PATH_E)eRFPath)) { 1538fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check Radio[%d] Fail!!\n", eRFPath); 1548fc8598eSJerry Chuang goto phy_RF8256_Config_ParaFile_Fail; 1558fc8598eSJerry Chuang } 1568fc8598eSJerry Chuang 1578fc8598eSJerry Chuang RetryTimes = ConstRetryTimes; 1588fc8598eSJerry Chuang RF3_Final_Value = 0; 1598fc8598eSJerry Chuang /*----Initialize RF fom connfiguration file----*/ 160104cb5c0SSanjeev Sharma switch (eRFPath) { 1618fc8598eSJerry Chuang case RF90_PATH_A: 162104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 1638fc8598eSJerry Chuang ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (RF90_RADIO_PATH_E)eRFPath); 1648fc8598eSJerry Chuang RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits); 1658fc8598eSJerry Chuang RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value); 1668fc8598eSJerry Chuang RetryTimes--; 1678fc8598eSJerry Chuang } 1688fc8598eSJerry Chuang break; 1698fc8598eSJerry Chuang case RF90_PATH_B: 170104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 1718fc8598eSJerry Chuang ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (RF90_RADIO_PATH_E)eRFPath); 1728fc8598eSJerry Chuang RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (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_C: 178104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 1798fc8598eSJerry Chuang ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (RF90_RADIO_PATH_E)eRFPath); 1808fc8598eSJerry Chuang RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (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_D: 186104cb5c0SSanjeev Sharma while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) { 1878fc8598eSJerry Chuang ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (RF90_RADIO_PATH_E)eRFPath); 1888fc8598eSJerry Chuang RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (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 } 1948fc8598eSJerry Chuang 1958fc8598eSJerry Chuang /*----Restore RFENV control type----*/; 196104cb5c0SSanjeev Sharma switch (eRFPath) { 1978fc8598eSJerry Chuang case RF90_PATH_A: 1988fc8598eSJerry Chuang case RF90_PATH_C: 1998fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue); 2008fc8598eSJerry Chuang break; 2018fc8598eSJerry Chuang case RF90_PATH_B: 2028fc8598eSJerry Chuang case RF90_PATH_D: 2038fc8598eSJerry Chuang rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue); 2048fc8598eSJerry Chuang break; 2058fc8598eSJerry Chuang } 2068fc8598eSJerry Chuang 2078fc8598eSJerry Chuang if (ret) { 2088fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!", eRFPath); 2098fc8598eSJerry Chuang goto phy_RF8256_Config_ParaFile_Fail; 2108fc8598eSJerry Chuang } 2118fc8598eSJerry Chuang 2128fc8598eSJerry Chuang } 2138fc8598eSJerry Chuang 2148fc8598eSJerry Chuang RT_TRACE(COMP_PHY, "PHY Initialization Success\n"); 2158fc8598eSJerry Chuang return; 2168fc8598eSJerry Chuang 2178fc8598eSJerry Chuang phy_RF8256_Config_ParaFile_Fail: 2188fc8598eSJerry Chuang RT_TRACE(COMP_ERR, "PHY Initialization failed\n"); 2198fc8598eSJerry Chuang } 2208fc8598eSJerry Chuang 2218fc8598eSJerry Chuang 2228fc8598eSJerry Chuang void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel) 2238fc8598eSJerry Chuang { 2248fc8598eSJerry Chuang u32 TxAGC = 0; 2258fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 2268fc8598eSJerry Chuang TxAGC = powerlevel; 2278fc8598eSJerry Chuang 228104cb5c0SSanjeev Sharma if (priv->bDynamicTxLowPower == TRUE) { 2298fc8598eSJerry Chuang if (priv->CustomerID == RT_CID_819x_Netcore) 2308fc8598eSJerry Chuang TxAGC = 0x22; 2318fc8598eSJerry Chuang else 2328fc8598eSJerry Chuang TxAGC += priv->CckPwEnl; 2338fc8598eSJerry Chuang } 2348fc8598eSJerry Chuang 2358fc8598eSJerry Chuang if (TxAGC > 0x24) 2368fc8598eSJerry Chuang TxAGC = 0x24; 2378fc8598eSJerry Chuang rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); 2388fc8598eSJerry Chuang } 2398fc8598eSJerry Chuang 2408fc8598eSJerry Chuang 2418fc8598eSJerry Chuang void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel) 2428fc8598eSJerry Chuang { 2438fc8598eSJerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 24493a9f05aSSanjeev Sharma /* Joseph TxPower for 8192 testing */ 2458fc8598eSJerry Chuang u32 writeVal, powerBase0, powerBase1, writeVal_tmp; 2468fc8598eSJerry Chuang u8 index = 0; 2478fc8598eSJerry Chuang u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; 2488fc8598eSJerry Chuang u8 byte0, byte1, byte2, byte3; 2498fc8598eSJerry Chuang 25093a9f05aSSanjeev Sharma powerBase0 = powerlevel + priv->TxPowerDiff; /* OFDM rates */ 2518fc8598eSJerry Chuang powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0; 25293a9f05aSSanjeev Sharma powerBase1 = powerlevel; /* MCS rates */ 2538fc8598eSJerry Chuang powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1; 2548fc8598eSJerry Chuang 255104cb5c0SSanjeev Sharma for (index = 0; index < 6; index++) { 2568fc8598eSJerry Chuang writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index < 2)?powerBase0:powerBase1); 2578fc8598eSJerry Chuang byte0 = (u8)(writeVal & 0x7f); 2588fc8598eSJerry Chuang byte1 = (u8)((writeVal & 0x7f00)>>8); 2598fc8598eSJerry Chuang byte2 = (u8)((writeVal & 0x7f0000)>>16); 2608fc8598eSJerry Chuang byte3 = (u8)((writeVal & 0x7f000000)>>24); 261104cb5c0SSanjeev Sharma 262104cb5c0SSanjeev Sharma if (byte0 > 0x24) 263104cb5c0SSanjeev Sharma /* Max power index = 0x24 */ 2648fc8598eSJerry Chuang byte0 = 0x24; 2658fc8598eSJerry Chuang if (byte1 > 0x24) 2668fc8598eSJerry Chuang byte1 = 0x24; 2678fc8598eSJerry Chuang if (byte2 > 0x24) 2688fc8598eSJerry Chuang byte2 = 0x24; 2698fc8598eSJerry Chuang if (byte3 > 0x24) 2708fc8598eSJerry Chuang byte3 = 0x24; 2718fc8598eSJerry Chuang 27293a9f05aSSanjeev Sharma /* for tx power track */ 273104cb5c0SSanjeev Sharma if (index == 3) { 2748fc8598eSJerry Chuang writeVal_tmp = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0; 2758fc8598eSJerry Chuang priv->Pwr_Track = writeVal_tmp; 2768fc8598eSJerry Chuang } 2778fc8598eSJerry Chuang 278104cb5c0SSanjeev Sharma if (priv->bDynamicTxHighPower == TRUE) { 279104cb5c0SSanjeev Sharma /*Add by Jacken 2008/03/06 280104cb5c0SSanjeev Sharma *Emily, 20080613. Set low tx power for both MCS and legacy OFDM 281104cb5c0SSanjeev Sharma */ 2828fc8598eSJerry Chuang writeVal = 0x03030303; 283104cb5c0SSanjeev Sharma } else { 2848fc8598eSJerry Chuang writeVal = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0; 2858fc8598eSJerry Chuang } 2868fc8598eSJerry Chuang rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); 2878fc8598eSJerry Chuang } 2888fc8598eSJerry Chuang return; 2898fc8598eSJerry Chuang 2908fc8598eSJerry Chuang } 291