8dcced6cb280b52ce430df03993e1b7739021da3
[openwrt/staging/mkresin.git] / package / kernel / mac80211 / patches / 655-rtl8xxxu-Implement-8192e-specific-power-down-sequenc.patch
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
5
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.
8
9 Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
10 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
11 ---
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(-)
15
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:
19 return ret;
20 }
21
22 +static int rtl8192eu_active_to_lps(struct rtl8xxxu_priv *priv)
23 +{
24 + struct device *dev = &priv->udev->dev;
25 + u8 val8;
26 + u16 val16;
27 + u32 val32;
28 + int retry, retval;
29 +
30 + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
31 +
32 + retry = 100;
33 + retval = -EBUSY;
34 + /*
35 + * Poll 32 bit wide 0x05f8 for 0x00000000 to ensure no TX is pending.
36 + */
37 + do {
38 + val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD);
39 + if (!val32) {
40 + retval = 0;
41 + break;
42 + }
43 + } while (retry--);
44 +
45 + if (!retry) {
46 + dev_warn(dev, "Failed to flush TX queue\n");
47 + retval = -EBUSY;
48 + goto out;
49 + }
50 +
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);
55 +
56 + udelay(2);
57 +
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);
62 +
63 + /* Reset MAC TRX */
64 + val16 = rtl8xxxu_read16(priv, REG_CR);
65 + val16 &= 0xff00;
66 + val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE);
67 + rtl8xxxu_write16(priv, REG_CR, val16);
68 +
69 + val16 = rtl8xxxu_read16(priv, REG_CR);
70 + val16 &= ~CR_SECURITY_ENABLE;
71 + rtl8xxxu_write16(priv, REG_CR, val16);
72 +
73 + val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST);
74 + val8 |= DUAL_TSF_TX_OK;
75 + rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val8);
76 +
77 +out:
78 + return retval;
79 +}
80 +
81 +static int rtl8192eu_active_to_emu(struct rtl8xxxu_priv *priv)
82 +{
83 + u8 val8;
84 + int count, ret = 0;
85 +
86 + /* Turn off RF */
87 + rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
88 +
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);
93 +
94 + /* 0x0005[1] = 1 turn off MAC by HW state machine*/
95 + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
96 + val8 |= BIT(1);
97 + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
98 +
99 + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
100 + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
101 + if ((val8 & BIT(1)) == 0)
102 + break;
103 + udelay(10);
104 + }
105 +
106 + if (!count) {
107 + dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n",
108 + __func__);
109 + ret = -EBUSY;
110 + goto exit;
111 + }
112 +
113 +exit:
114 + return ret;
115 +}
116 +
117 +static int rtl8192eu_emu_to_disabled(struct rtl8xxxu_priv *priv)
118 +{
119 + u8 val8;
120 +
121 + /* 0x04[12:11] = 01 enable WL suspend */
122 + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
123 + val8 &= ~(BIT(3) | BIT(4));
124 + val8 |= BIT(3);
125 + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
126 +
127 + return 0;
128 +}
129 +
130 static int rtl8192eu_power_on(struct rtl8xxxu_priv *priv)
131 {
132 u16 val16;
133 @@ -1446,6 +1554,40 @@ exit:
134 return ret;
135 }
136
137 +void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
138 +{
139 + u8 val8;
140 + u16 val16;
141 +
142 + rtl8xxxu_flush_fifo(priv);
143 +
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);
147 +
148 + /* Turn off RF */
149 + rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00);
150 +
151 + rtl8192eu_active_to_lps(priv);
152 +
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);
156 +
157 + /* Reset MCU */
158 + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
159 + val16 &= ~SYS_FUNC_CPU_ENABLE;
160 + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
161 +
162 + /* Reset MCU ready status */
163 + rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
164 +
165 + rtl8xxxu_reset_8051(priv);
166 +
167 + rtl8192eu_active_to_emu(priv);
168 + rtl8192eu_emu_to_disabled(priv);
169 +}
170 +
171 static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv)
172 {
173 u32 val32;
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
185 @@ -676,6 +676,7 @@
186 #define REG_SCH_TXCMD 0x05d0
187
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