Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtlwifi: rtl8192c: rtl8192ce: Add support for B-CUT version of RTL8188CE

Realtek devices with designation RTL8188CE-VL have the so-called B-cut
of the wireless chip. This patch adds the special programming needed by
these devices. In addition, a variable that was static has been moved into
the private data area as it is now needed in two different routines. This
change also fixes a minor bug that would be present if a system had more
than one RTL81{88,92}CE devices. Other drivers in the rtlwifi family had
already made this change, thus the variable already exists in the private
data structure.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Anisse Astier <anisse@astier.eu>
Cc: Li Chaoming <chaoming_li@realsil.com.cn>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Larry Finger and committed by
John W. Linville
0bd899e7 ab3d59d2

+85 -11
+21
drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
··· 724 724 } 725 725 EXPORT_SYMBOL(rtl92c_phy_sw_chnl); 726 726 727 + static void _rtl92c_phy_sw_rf_setting(struct ieee80211_hw *hw, u8 channel) 728 + { 729 + struct rtl_priv *rtlpriv = rtl_priv(hw); 730 + struct rtl_phy *rtlphy = &(rtlpriv->phy); 731 + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 732 + 733 + if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { 734 + if (channel == 6 && rtlphy->current_chan_bw == 735 + HT_CHANNEL_WIDTH_20) 736 + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 737 + 0x00255); 738 + else{ 739 + u32 backupRF0x1A = (u32)rtl_get_rfreg(hw, RF90_PATH_A, 740 + RF_RX_G1, RFREG_OFFSET_MASK); 741 + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 742 + backupRF0x1A); 743 + } 744 + } 745 + } 746 + 727 747 static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, 728 748 u32 cmdtableidx, u32 cmdtablesz, 729 749 enum swchnlcmd_id cmdid, ··· 857 837 currentcmd->para1, 858 838 RFREG_OFFSET_MASK, 859 839 rtlphy->rfreg_chnlval[rfpath]); 840 + _rtl92c_phy_sw_rf_setting(hw, channel); 860 841 } 861 842 break; 862 843 default:
+3
drivers/net/wireless/rtlwifi/rtl8192ce/def.h
··· 116 116 LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) 117 117 118 118 #define CHIP_VER_B BIT(4) 119 + #define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) 120 + #define CHIP_BONDING_92C_1T2R 0x1 121 + #define RF_TYPE_1T2R BIT(1) 119 122 #define CHIP_92C_BITMASK BIT(0) 120 123 #define CHIP_UNKNOWN BIT(7) 121 124 #define CHIP_92C_1T2R 0x03
+55 -5
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
··· 896 896 struct rtl_phy *rtlphy = &(rtlpriv->phy); 897 897 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 898 898 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 899 - static bool iqk_initialized; /* initialized to false */ 900 899 bool rtstatus = true; 901 900 bool is92c; 902 901 int err; ··· 920 921 921 922 rtlhal->last_hmeboxnum = 0; 922 923 rtl92c_phy_mac_config(hw); 924 + /* because last function modify RCR, so we update 925 + * rcr var here, or TP will unstable for receive_config 926 + * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx 927 + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/ 928 + rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); 929 + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); 930 + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); 923 931 rtl92c_phy_bb_config(hw); 924 932 rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; 925 933 rtl92c_phy_rf_config(hw); 934 + if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && 935 + !IS_92C_SERIAL(rtlhal->version)) { 936 + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255); 937 + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00); 938 + } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { 939 + rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE); 940 + rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31); 941 + rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425); 942 + rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200); 943 + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053); 944 + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201); 945 + } 926 946 rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, 927 947 RF_CHNLBW, RFREG_OFFSET_MASK); 928 948 rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, ··· 963 945 964 946 if (ppsc->rfpwr_state == ERFON) { 965 947 rtl92c_phy_set_rfpath_switch(hw, 1); 966 - if (iqk_initialized) { 948 + if (rtlphy->iqk_initialized) { 967 949 rtl92c_phy_iq_calibrate(hw, true); 968 950 } else { 969 951 rtl92c_phy_iq_calibrate(hw, false); 970 - iqk_initialized = true; 952 + rtlphy->iqk_initialized = true; 971 953 } 972 954 973 955 rtl92c_dm_check_txpower_tracking(hw); ··· 1022 1004 ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | 1023 1005 CHIP_VENDOR_UMC)); 1024 1006 } 1007 + if (IS_92C_SERIAL(version)) { 1008 + value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM); 1009 + version = (enum version_8192c)(version | 1010 + ((CHIP_BONDING_IDENTIFIER(value32) 1011 + == CHIP_BONDING_92C_1T2R) ? 1012 + RF_TYPE_1T2R : 0)); 1013 + } 1025 1014 } 1026 1015 1027 1016 switch (version) { ··· 1044 1019 case VERSION_A_CHIP_88C: 1045 1020 versionid = "A_CHIP_88C"; 1046 1021 break; 1022 + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT: 1023 + versionid = "A_CUT_92C_1T2R"; 1024 + break; 1025 + case VERSION_NORMAL_UMC_CHIP_92C_A_CUT: 1026 + versionid = "A_CUT_92C"; 1027 + break; 1028 + case VERSION_NORMAL_UMC_CHIP_88C_A_CUT: 1029 + versionid = "A_CUT_88C"; 1030 + break; 1031 + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT: 1032 + versionid = "B_CUT_92C_1T2R"; 1033 + break; 1034 + case VERSION_NORMAL_UMC_CHIP_92C_B_CUT: 1035 + versionid = "B_CUT_92C"; 1036 + break; 1037 + case VERSION_NORMAL_UMC_CHIP_88C_B_CUT: 1038 + versionid = "B_CUT_88C"; 1039 + break; 1047 1040 default: 1048 1041 versionid = "Unknown. Bug?"; 1049 1042 break; 1050 1043 } 1051 1044 1052 - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, 1045 + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, 1053 1046 "Chip Version ID: %s\n", versionid); 1054 1047 1055 1048 switch (version & 0x3) { ··· 1240 1197 { 1241 1198 struct rtl_priv *rtlpriv = rtl_priv(hw); 1242 1199 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); 1200 + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 1243 1201 u8 u1b_tmp; 1244 1202 u32 u4b_tmp; 1245 1203 ··· 1269 1225 rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); 1270 1226 rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); 1271 1227 rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); 1272 - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); 1228 + if (!IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) 1229 + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); 1273 1230 if (rtlpcipriv->bt_coexist.bt_coexistence) { 1274 1231 u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); 1275 1232 u4b_tmp |= 0x03824800; ··· 1299 1254 rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); 1300 1255 RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); 1301 1256 _rtl92ce_poweroff_adapter(hw); 1257 + 1258 + /* after power off we should do iqk again */ 1259 + rtlpriv->phy.iqk_initialized = false; 1302 1260 } 1303 1261 1304 1262 void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw, ··· 1960 1912 ratr_bitmap &= 0x0f0ff0ff; 1961 1913 break; 1962 1914 } 1915 + sta_entry->ratr_index = ratr_index; 1916 + 1963 1917 RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, 1964 1918 "ratr_bitmap :%x\n", ratr_bitmap); 1965 1919 *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
+2
drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
··· 82 82 83 83 if (is92c) 84 84 rtl_write_byte(rtlpriv, 0x14, 0x71); 85 + else 86 + rtl_write_byte(rtlpriv, 0x04CA, 0x0A); 85 87 return rtstatus; 86 88 } 87 89
+2 -4
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
··· 162 162 163 163 /* request fw */ 164 164 if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && 165 - !IS_92C_SERIAL(rtlhal->version)) { 165 + !IS_92C_SERIAL(rtlhal->version)) 166 166 rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; 167 - } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { 167 + else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) 168 168 rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; 169 - pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n"); 170 - } 171 169 172 170 rtlpriv->max_fw_size = 0x4000; 173 171 pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
+2 -2
drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
··· 127 127 { 128 128 struct rtl_priv *rtlpriv = rtl_priv(hw); 129 129 struct phy_sts_cck_8192s_t *cck_buf; 130 + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); 130 131 s8 rx_pwr_all = 0, rx_pwr[4]; 131 132 u8 evm, pwdb_all, rf_rx_num = 0; 132 133 u8 i, max_spatial_stream; 133 134 u32 rssi, total_rssi = 0; 134 - bool in_powersavemode = false; 135 135 bool is_cck_rate; 136 136 137 137 is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); ··· 147 147 u8 report, cck_highpwr; 148 148 cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; 149 149 150 - if (!in_powersavemode) 150 + if (ppsc->rfpwr_state == ERFON) 151 151 cck_highpwr = (u8) rtl_get_bbreg(hw, 152 152 RFPGA0_XA_HSSIPARAMETER2, 153 153 BIT(9));