rtl8xxxu: add support for rtl8188eu
[openwrt/staging/dedeckeh.git] / package / kernel / mac80211 / patches / 651-0023-rtl8xxxu-Implement-8192e-specific-power-down-sequenc.patch
1 From c37241da2ccb981598ed4bf243f86228aca292b6 Mon Sep 17 00:00:00 2001
2 From: Jes Sorensen <Jes.Sorensen@redhat.com>
3 Date: Tue, 13 Sep 2016 14:51:43 -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 ---
11 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | 144 ++++++++++++++++++++-
12 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 1 +
13 2 files changed, 144 insertions(+), 1 deletion(-)
14
15 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
16 +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
17 @@ -1396,6 +1396,114 @@ exit:
18 return ret;
19 }
20
21 +static int rtl8192eu_active_to_lps(struct rtl8xxxu_priv *priv)
22 +{
23 + struct device *dev = &priv->udev->dev;
24 + u8 val8;
25 + u16 val16;
26 + u32 val32;
27 + int retry, retval;
28 +
29 + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
30 +
31 + retry = 100;
32 + retval = -EBUSY;
33 + /*
34 + * Poll 32 bit wide 0x05f8 for 0x00000000 to ensure no TX is pending.
35 + */
36 + do {
37 + val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD);
38 + if (!val32) {
39 + retval = 0;
40 + break;
41 + }
42 + } while (retry--);
43 +
44 + if (!retry) {
45 + dev_warn(dev, "Failed to flush TX queue\n");
46 + retval = -EBUSY;
47 + goto out;
48 + }
49 +
50 + /* Disable CCK and OFDM, clock gated */
51 + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
52 + val8 &= ~SYS_FUNC_BBRSTB;
53 + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
54 +
55 + udelay(2);
56 +
57 + /* Reset whole BB */
58 + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
59 + val8 &= ~SYS_FUNC_BB_GLB_RSTN;
60 + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
61 +
62 + /* Reset MAC TRX */
63 + val16 = rtl8xxxu_read16(priv, REG_CR);
64 + val16 &= 0xff00;
65 + val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE);
66 + rtl8xxxu_write16(priv, REG_CR, val16);
67 +
68 + val16 = rtl8xxxu_read16(priv, REG_CR);
69 + val16 &= ~CR_SECURITY_ENABLE;
70 + rtl8xxxu_write16(priv, REG_CR, val16);
71 +
72 + val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST);
73 + val8 |= DUAL_TSF_TX_OK;
74 + rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val8);
75 +
76 +out:
77 + return retval;
78 +}
79 +
80 +static int rtl8192eu_active_to_emu(struct rtl8xxxu_priv *priv)
81 +{
82 + u8 val8;
83 + int count, ret = 0;
84 +
85 + /* Turn off RF */
86 + rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
87 +
88 + /* Switch DPDT_SEL_P output from register 0x65[2] */
89 + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
90 + val8 &= ~LEDCFG2_DPDT_SELECT;
91 + rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
92 +
93 + /* 0x0005[1] = 1 turn off MAC by HW state machine*/
94 + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
95 + val8 |= BIT(1);
96 + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
97 +
98 + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
99 + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
100 + if ((val8 & BIT(1)) == 0)
101 + break;
102 + udelay(10);
103 + }
104 +
105 + if (!count) {
106 + dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n",
107 + __func__);
108 + ret = -EBUSY;
109 + goto exit;
110 + }
111 +
112 +exit:
113 + return ret;
114 +}
115 +
116 +static int rtl8192eu_emu_to_disabled(struct rtl8xxxu_priv *priv)
117 +{
118 + u8 val8;
119 +
120 + /* 0x04[12:11] = 01 enable WL suspend */
121 + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
122 + val8 &= ~(BIT(3) | BIT(4));
123 + val8 |= BIT(3);
124 + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
125 +
126 + return 0;
127 +}
128 +
129 static int rtl8192eu_power_on(struct rtl8xxxu_priv *priv)
130 {
131 u16 val16;
132 @@ -1446,6 +1554,40 @@ exit:
133 return ret;
134 }
135
136 +void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
137 +{
138 + u8 val8;
139 + u16 val16;
140 +
141 + rtl8xxxu_flush_fifo(priv);
142 +
143 + val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL);
144 + val8 &= ~TX_REPORT_CTRL_TIMER_ENABLE;
145 + rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8);
146 +
147 + /* Turn off RF */
148 + rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00);
149 +
150 + rtl8192eu_active_to_lps(priv);
151 +
152 + /* Reset Firmware if running in RAM */
153 + if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
154 + rtl8xxxu_firmware_self_reset(priv);
155 +
156 + /* Reset MCU */
157 + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
158 + val16 &= ~SYS_FUNC_CPU_ENABLE;
159 + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
160 +
161 + /* Reset MCU ready status */
162 + rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
163 +
164 + rtl8xxxu_reset_8051(priv);
165 +
166 + rtl8192eu_active_to_emu(priv);
167 + rtl8192eu_emu_to_disabled(priv);
168 +}
169 +
170 static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv)
171 {
172 u32 val32;
173 @@ -1487,7 +1629,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops =
174 .parse_efuse = rtl8192eu_parse_efuse,
175 .load_firmware = rtl8192eu_load_firmware,
176 .power_on = rtl8192eu_power_on,
177 - .power_off = rtl8xxxu_power_off,
178 + .power_off = rtl8192eu_power_off,
179 .reset_8051 = rtl8xxxu_reset_8051,
180 .llt_init = rtl8xxxu_auto_llt_table,
181 .init_phy_bb = rtl8192eu_init_phy_bb,
182 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
183 +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
184 @@ -676,6 +676,7 @@
185 #define REG_SCH_TXCMD 0x05d0
186
187 /* define REG_FW_TSF_SYNC_CNT 0x04a0 */
188 +#define REG_SCH_TX_CMD 0x05f8
189 #define REG_FW_RESET_TSF_CNT_1 0x05fc
190 #define REG_FW_RESET_TSF_CNT_0 0x05fd
191 #define REG_FW_BCN_DIS_CNT 0x05fe