rtl8xxxu: Implement device specific power_off function
authorJes Sorensen <Jes.Sorensen@redhat.com>
Mon, 29 Feb 2016 22:05:47 +0000 (17:05 -0500)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 10 Mar 2016 13:29:20 +0000 (15:29 +0200)
Implment 8723bu specific device power down, and make power_off() a
fileops function.

Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h

index 50d2c5c8c153faf911a71c87ef5330da16483af4..ef60e83ababd89a08a5e6fec59384e8be56dd2dc 100644 (file)
@@ -5240,6 +5240,64 @@ exit:
        return ret;
 }
 
+static int rtl8723bu_active_to_emu(struct rtl8xxxu_priv *priv)
+{
+       u8 val8;
+       u16 val16;
+       u32 val32;
+       int count, ret;
+
+       /* Turn off RF */
+       rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
+
+       /* Enable rising edge triggering interrupt */
+       val16 = rtl8xxxu_read16(priv, REG_GPIO_INTM);
+       val16 &= ~GPIO_INTM_EDGE_TRIG_IRQ;
+       rtl8xxxu_write16(priv, REG_GPIO_INTM, val16);
+
+       /* Release WLON reset 0x04[16]= 1*/
+       val32 = rtl8xxxu_read32(priv, REG_GPIO_INTM);
+       val32 |= APS_FSMCO_WLON_RESET;
+       rtl8xxxu_write32(priv, REG_GPIO_INTM, val32);
+
+       /* 0x0005[1] = 1 turn off MAC by HW state machine*/
+       val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+       val8 |= BIT(1);
+       rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
+
+       for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+               val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+               if ((val8 & BIT(1)) == 0)
+                       break;
+               udelay(10);
+       }
+
+       if (!count) {
+               dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n",
+                        __func__);
+               ret = -EBUSY;
+               goto exit;
+       }
+
+       /* Enable BT control XTAL setting */
+       val8 = rtl8xxxu_read8(priv, REG_AFE_MISC);
+       val8 &= ~AFE_MISC_WL_XTAL_CTRL;
+       rtl8xxxu_write8(priv, REG_AFE_MISC, val8);
+
+       /* 0x0000[5] = 1 analog Ips to digital, 1:isolation */
+       val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
+       val8 |= SYS_ISO_ANALOG_IPS;
+       rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
+
+       /* 0x0020[0] = 0 disable LDOA12 MACRO block*/
+       val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL);
+       val8 &= ~LDOA15_ENABLE;
+       rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8);
+
+exit:
+       return ret;
+}
+
 static int rtl8xxxu_active_to_lps(struct rtl8xxxu_priv *priv)
 {
        u8 val8;
@@ -5932,6 +5990,38 @@ static void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv)
        rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e);
 }
 
+static void rtl8723bu_power_off(struct rtl8xxxu_priv *priv)
+{
+       u8 val8;
+       u16 val16;
+
+       /*
+        * Disable TX report timer
+        */
+       val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL);
+       val8 &= ~TX_REPORT_CTRL_TIMER_ENABLE;
+       rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8);
+
+       rtl8xxxu_write16(priv, REG_CR, 0x0000);
+
+       rtl8xxxu_active_to_lps(priv);
+
+       /* Reset Firmware if running in RAM */
+       if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
+               rtl8xxxu_firmware_self_reset(priv);
+
+       /* Reset MCU */
+       val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
+       val16 &= ~SYS_FUNC_CPU_ENABLE;
+       rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
+
+       /* Reset MCU ready status */
+       rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
+
+       rtl8723bu_active_to_emu(priv);
+       rtl8xxxu_emu_to_disabled(priv);
+}
+
 #ifdef NEED_PS_TDMA
 static void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
                                  u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5)
@@ -6152,7 +6242,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
                 */
                if (priv->rtlchip == 0x8723bu) {
                        val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL);
-                       val8 |= BIT(1);
+                       val8 |= TX_REPORT_CTRL_TIMER_ENABLE;
                        rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8);
                        /* Set MAX RPT MACID */
                        rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL + 1, 0x02);
@@ -6545,7 +6635,7 @@ static void rtl8xxxu_disable_device(struct ieee80211_hw *hw)
 {
        struct rtl8xxxu_priv *priv = hw->priv;
 
-       rtl8xxxu_power_off(priv);
+       priv->fops->power_off(priv);
 }
 
 static void rtl8xxxu_cam_write(struct rtl8xxxu_priv *priv,
@@ -8277,6 +8367,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = {
        .parse_efuse = rtl8723au_parse_efuse,
        .load_firmware = rtl8723au_load_firmware,
        .power_on = rtl8723au_power_on,
+       .power_off = rtl8xxxu_power_off,
        .llt_init = rtl8xxxu_init_llt_table,
        .phy_iq_calibrate = rtl8723au_phy_iq_calibrate,
        .config_channel = rtl8723au_config_channel,
@@ -8300,6 +8391,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = {
        .parse_efuse = rtl8723bu_parse_efuse,
        .load_firmware = rtl8723bu_load_firmware,
        .power_on = rtl8723bu_power_on,
+       .power_off = rtl8723bu_power_off,
        .llt_init = rtl8xxxu_auto_llt_table,
        .phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection,
        .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate,
@@ -8329,6 +8421,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = {
        .parse_efuse = rtl8192cu_parse_efuse,
        .load_firmware = rtl8192cu_load_firmware,
        .power_on = rtl8192cu_power_on,
+       .power_off = rtl8xxxu_power_off,
        .llt_init = rtl8xxxu_init_llt_table,
        .phy_iq_calibrate = rtl8723au_phy_iq_calibrate,
        .config_channel = rtl8723au_config_channel,
@@ -8354,6 +8447,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = {
        .parse_efuse = rtl8192eu_parse_efuse,
        .load_firmware = rtl8192eu_load_firmware,
        .power_on = rtl8192eu_power_on,
+       .power_off = rtl8xxxu_power_off,
        .llt_init = rtl8xxxu_auto_llt_table,
        .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate,
        .config_channel = rtl8723bu_config_channel,
index 9c535e8dbecfa56c1b3c90229cfafb176f0b2b40..bfa9d6c5d502fe22bce81c532b63fb7d4c065bfe 100644 (file)
@@ -1257,6 +1257,7 @@ struct rtl8xxxu_fileops {
        int (*parse_efuse) (struct rtl8xxxu_priv *priv);
        int (*load_firmware) (struct rtl8xxxu_priv *priv);
        int (*power_on) (struct rtl8xxxu_priv *priv);
+       void (*power_off) (struct rtl8xxxu_priv *priv);
        int (*llt_init) (struct rtl8xxxu_priv *priv, u8 last_tx_page);
        void (*phy_init_antenna_selection) (struct rtl8xxxu_priv *priv);
        void (*phy_iq_calibrate) (struct rtl8xxxu_priv *priv);
index e0b9ea3811c06338d97295bc28d36f787cbc1b67..a8d5c9f98051bcb5676bf8269b2412601037007b 100644 (file)
 #define REG_PKT_LOSE_RPT               0x04e1
 #define REG_PTCL_ERR_STATUS            0x04e2
 #define REG_TX_REPORT_CTRL             0x04ec
+#define  TX_REPORT_CTRL_TIMER_ENABLE   BIT(1)
+
 #define REG_TX_REPORT_TIME             0x04f0
 #define REG_DUMMY                      0x04fc