1 From f1785fbf7c0bc17211c299a647ebc38968a42181 Mon Sep 17 00:00:00 2001
2 From: Jes Sorensen <Jes.Sorensen@redhat.com>
3 Date: Tue, 13 Sep 2016 15:03:15 -0400
4 Subject: [PATCH] rtl8xxxu: Implement 8192e specific power down sequence
6 This powers down the 8192e correctly, or at least to the point where
7 the firmware will load again, when reloading the driver module.
9 Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
10 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
12 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | 144 ++++++++++++++++++++-
13 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 1 +
14 2 files changed, 144 insertions(+), 1 deletion(-)
16 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
17 +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
18 @@ -1396,6 +1396,114 @@ exit:
22 +static int rtl8192eu_active_to_lps(struct rtl8xxxu_priv *priv)
24 + struct device *dev = &priv->udev->dev;
30 + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
35 + * Poll 32 bit wide 0x05f8 for 0x00000000 to ensure no TX is pending.
38 + val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD);
46 + dev_warn(dev, "Failed to flush TX queue\n");
51 + /* Disable CCK and OFDM, clock gated */
52 + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
53 + val8 &= ~SYS_FUNC_BBRSTB;
54 + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
58 + /* Reset whole BB */
59 + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
60 + val8 &= ~SYS_FUNC_BB_GLB_RSTN;
61 + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
64 + val16 = rtl8xxxu_read16(priv, REG_CR);
66 + val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE);
67 + rtl8xxxu_write16(priv, REG_CR, val16);
69 + val16 = rtl8xxxu_read16(priv, REG_CR);
70 + val16 &= ~CR_SECURITY_ENABLE;
71 + rtl8xxxu_write16(priv, REG_CR, val16);
73 + val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST);
74 + val8 |= DUAL_TSF_TX_OK;
75 + rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val8);
81 +static int rtl8192eu_active_to_emu(struct rtl8xxxu_priv *priv)
87 + rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
89 + /* Switch DPDT_SEL_P output from register 0x65[2] */
90 + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
91 + val8 &= ~LEDCFG2_DPDT_SELECT;
92 + rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
94 + /* 0x0005[1] = 1 turn off MAC by HW state machine*/
95 + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
97 + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
99 + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
100 + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
101 + if ((val8 & BIT(1)) == 0)
107 + dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n",
117 +static int rtl8192eu_emu_to_disabled(struct rtl8xxxu_priv *priv)
121 + /* 0x04[12:11] = 01 enable WL suspend */
122 + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
123 + val8 &= ~(BIT(3) | BIT(4));
125 + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
130 static int rtl8192eu_power_on(struct rtl8xxxu_priv *priv)
133 @@ -1446,6 +1554,40 @@ exit:
137 +void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
142 + rtl8xxxu_flush_fifo(priv);
144 + val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL);
145 + val8 &= ~TX_REPORT_CTRL_TIMER_ENABLE;
146 + rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8);
149 + rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00);
151 + rtl8192eu_active_to_lps(priv);
153 + /* Reset Firmware if running in RAM */
154 + if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
155 + rtl8xxxu_firmware_self_reset(priv);
158 + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
159 + val16 &= ~SYS_FUNC_CPU_ENABLE;
160 + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
162 + /* Reset MCU ready status */
163 + rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
165 + rtl8xxxu_reset_8051(priv);
167 + rtl8192eu_active_to_emu(priv);
168 + rtl8192eu_emu_to_disabled(priv);
171 static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv)
174 @@ -1487,7 +1629,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops =
175 .parse_efuse = rtl8192eu_parse_efuse,
176 .load_firmware = rtl8192eu_load_firmware,
177 .power_on = rtl8192eu_power_on,
178 - .power_off = rtl8xxxu_power_off,
179 + .power_off = rtl8192eu_power_off,
180 .reset_8051 = rtl8xxxu_reset_8051,
181 .llt_init = rtl8xxxu_auto_llt_table,
182 .init_phy_bb = rtl8192eu_init_phy_bb,
183 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
184 +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
186 #define REG_SCH_TXCMD 0x05d0
188 /* define REG_FW_TSF_SYNC_CNT 0x04a0 */
189 +#define REG_SCH_TX_CMD 0x05f8
190 #define REG_FW_RESET_TSF_CNT_1 0x05fc
191 #define REG_FW_RESET_TSF_CNT_0 0x05fd
192 #define REG_FW_BCN_DIS_CNT 0x05fe