rtlwifi: rtl8192c: rtl8192ce: Add support for B-CUT version of RTL8188CE
authorLarry Finger <Larry.Finger@lwfinger.net>
Thu, 25 Oct 2012 18:46:30 +0000 (13:46 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 30 Oct 2012 20:17:53 +0000 (16:17 -0400)
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>
drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
drivers/net/wireless/rtlwifi/rtl8192ce/def.h
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
drivers/net/wireless/rtlwifi/rtl8192ce/trx.c

index cdcad7d..6ae2268 100644 (file)
@@ -724,6 +724,26 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(rtl92c_phy_sw_chnl);
 
+static void _rtl92c_phy_sw_rf_setting(struct ieee80211_hw *hw, u8 channel)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &(rtlpriv->phy);
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+       if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+               if (channel == 6 && rtlphy->current_chan_bw ==
+                   HT_CHANNEL_WIDTH_20)
+                       rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+                                     0x00255);
+               else{
+                       u32 backupRF0x1A = (u32)rtl_get_rfreg(hw, RF90_PATH_A,
+                                           RF_RX_G1, RFREG_OFFSET_MASK);
+                       rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+                                     backupRF0x1A);
+               }
+       }
+}
+
 static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
                                             u32 cmdtableidx, u32 cmdtablesz,
                                             enum swchnlcmd_id cmdid,
@@ -837,6 +857,7 @@ bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
                                              currentcmd->para1,
                                              RFREG_OFFSET_MASK,
                                              rtlphy->rfreg_chnlval[rfpath]);
+                       _rtl92c_phy_sw_rf_setting(hw, channel);
                        }
                        break;
                default:
index 2925094..3cfa1bb 100644 (file)
        LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
 
 #define CHIP_VER_B                     BIT(4)
+#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3)
+#define CHIP_BONDING_92C_1T2R          0x1
+#define RF_TYPE_1T2R                   BIT(1)
 #define CHIP_92C_BITMASK               BIT(0)
 #define CHIP_UNKNOWN                   BIT(7)
 #define CHIP_92C_1T2R                  0x03
index 038c02c..7dc7ac8 100644 (file)
@@ -896,7 +896,6 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
        struct rtl_phy *rtlphy = &(rtlpriv->phy);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-       static bool iqk_initialized; /* initialized to false */
        bool rtstatus = true;
        bool is92c;
        int err;
@@ -921,9 +920,28 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
 
        rtlhal->last_hmeboxnum = 0;
        rtl92c_phy_mac_config(hw);
+       /* because last function modify RCR, so we update
+        * rcr var here, or TP will unstable for receive_config
+        * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+        * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/
+       rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
+       rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+       rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
        rtl92c_phy_bb_config(hw);
        rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
        rtl92c_phy_rf_config(hw);
+       if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
+           !IS_92C_SERIAL(rtlhal->version)) {
+               rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
+               rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
+       } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+               rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE);
+               rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31);
+               rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425);
+               rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200);
+               rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053);
+               rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201);
+       }
        rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
                                                 RF_CHNLBW, RFREG_OFFSET_MASK);
        rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
@@ -945,11 +963,11 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
 
        if (ppsc->rfpwr_state == ERFON) {
                rtl92c_phy_set_rfpath_switch(hw, 1);
-               if (iqk_initialized) {
+               if (rtlphy->iqk_initialized) {
                        rtl92c_phy_iq_calibrate(hw, true);
                } else {
                        rtl92c_phy_iq_calibrate(hw, false);
-                       iqk_initialized = true;
+                       rtlphy->iqk_initialized = true;
                }
 
                rtl92c_dm_check_txpower_tracking(hw);
@@ -1004,6 +1022,13 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
                                   ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) |
                                   CHIP_VENDOR_UMC));
                }
+               if (IS_92C_SERIAL(version)) {
+                       value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
+                       version = (enum version_8192c)(version |
+                                  ((CHIP_BONDING_IDENTIFIER(value32)
+                                  == CHIP_BONDING_92C_1T2R) ?
+                                  RF_TYPE_1T2R : 0));
+               }
        }
 
        switch (version) {
@@ -1019,12 +1044,30 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
        case VERSION_A_CHIP_88C:
                versionid = "A_CHIP_88C";
                break;
+       case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
+               versionid = "A_CUT_92C_1T2R";
+               break;
+       case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
+               versionid = "A_CUT_92C";
+               break;
+       case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
+               versionid = "A_CUT_88C";
+               break;
+       case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
+               versionid = "B_CUT_92C_1T2R";
+               break;
+       case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
+               versionid = "B_CUT_92C";
+               break;
+       case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
+               versionid = "B_CUT_88C";
+               break;
        default:
                versionid = "Unknown. Bug?";
                break;
        }
 
-       RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
                 "Chip Version ID: %s\n", versionid);
 
        switch (version & 0x3) {
@@ -1197,6 +1240,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
        u8 u1b_tmp;
        u32 u4b_tmp;
 
@@ -1225,7 +1269,8 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
        rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790);
        rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
        rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
-       rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
+       if (!IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+               rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
        if (rtlpcipriv->bt_coexist.bt_coexistence) {
                u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL);
                u4b_tmp |= 0x03824800;
@@ -1254,6 +1299,9 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw)
                rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
        RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
        _rtl92ce_poweroff_adapter(hw);
+
+       /* after power off we should do iqk again */
+       rtlpriv->phy.iqk_initialized = false;
 }
 
 void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw,
@@ -1912,6 +1960,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
                        ratr_bitmap &= 0x0f0ff0ff;
                break;
        }
+       sta_entry->ratr_index = ratr_index;
+
        RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
                 "ratr_bitmap :%x\n", ratr_bitmap);
        *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
index 88deae6..73262ca 100644 (file)
@@ -82,6 +82,8 @@ bool rtl92c_phy_mac_config(struct ieee80211_hw *hw)
 
        if (is92c)
                rtl_write_byte(rtlpriv, 0x14, 0x71);
+       else
+               rtl_write_byte(rtlpriv, 0x04CA, 0x0A);
        return rtstatus;
 }
 
index ea2e1bd..60451ee 100644 (file)
@@ -162,12 +162,10 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
 
        /* request fw */
        if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
-           !IS_92C_SERIAL(rtlhal->version)) {
+           !IS_92C_SERIAL(rtlhal->version))
                rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin";
-       } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+       else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
                rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin";
-               pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n");
-       }
 
        rtlpriv->max_fw_size = 0x4000;
        pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
index 390d6d4..b8a3c03 100644 (file)
@@ -127,11 +127,11 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct phy_sts_cck_8192s_t *cck_buf;
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
        s8 rx_pwr_all = 0, rx_pwr[4];
        u8 evm, pwdb_all, rf_rx_num = 0;
        u8 i, max_spatial_stream;
        u32 rssi, total_rssi = 0;
-       bool in_powersavemode = false;
        bool is_cck_rate;
 
        is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
@@ -147,7 +147,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
                u8 report, cck_highpwr;
                cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
 
-               if (!in_powersavemode)
+               if (ppsc->rfpwr_state == ERFON)
                        cck_highpwr = (u8) rtl_get_bbreg(hw,
                                                 RFPGA0_XA_HSSIPARAMETER2,
                                                 BIT(9));