diff options
Diffstat (limited to 'drivers/net/wireless/rtlwifi/rtl8188ee/hw.c')
-rw-r--r-- | drivers/net/wireless/rtlwifi/rtl8188ee/hw.c | 2529 |
1 files changed, 2529 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c new file mode 100644 index 000000000000..d734d19a066f --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c | |||
@@ -0,0 +1,2529 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "wifi.h" | ||
31 | #include "efuse.h" | ||
32 | #include "base.h" | ||
33 | #include "regd.h" | ||
34 | #include "cam.h" | ||
35 | #include "ps.h" | ||
36 | #include "pci.h" | ||
37 | #include "reg.h" | ||
38 | #include "def.h" | ||
39 | #include "phy.h" | ||
40 | #include "dm.h" | ||
41 | #include "fw.h" | ||
42 | #include "led.h" | ||
43 | #include "hw.h" | ||
44 | #include "pwrseqcmd.h" | ||
45 | #include "pwrseq.h" | ||
46 | |||
47 | #define LLT_CONFIG 5 | ||
48 | |||
49 | static void _rtl88ee_set_bcn_ctrl_reg(struct ieee80211_hw *hw, | ||
50 | u8 set_bits, u8 clear_bits) | ||
51 | { | ||
52 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
53 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
54 | |||
55 | rtlpci->reg_bcn_ctrl_val |= set_bits; | ||
56 | rtlpci->reg_bcn_ctrl_val &= ~clear_bits; | ||
57 | |||
58 | rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); | ||
59 | } | ||
60 | |||
61 | static void _rtl88ee_stop_tx_beacon(struct ieee80211_hw *hw) | ||
62 | { | ||
63 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
64 | u8 tmp1byte; | ||
65 | |||
66 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); | ||
67 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); | ||
68 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); | ||
69 | tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); | ||
70 | tmp1byte &= ~(BIT(0)); | ||
71 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); | ||
72 | } | ||
73 | |||
74 | static void _rtl88ee_resume_tx_beacon(struct ieee80211_hw *hw) | ||
75 | { | ||
76 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
77 | u8 tmp1byte; | ||
78 | |||
79 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); | ||
80 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); | ||
81 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); | ||
82 | tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); | ||
83 | tmp1byte |= BIT(0); | ||
84 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); | ||
85 | } | ||
86 | |||
87 | static void _rtl88ee_enable_bcn_sub_func(struct ieee80211_hw *hw) | ||
88 | { | ||
89 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); | ||
90 | } | ||
91 | |||
92 | static void _rtl88ee_return_beacon_queue_skb(struct ieee80211_hw *hw) | ||
93 | { | ||
94 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
95 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
96 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; | ||
97 | |||
98 | while (skb_queue_len(&ring->queue)) { | ||
99 | struct rtl_tx_desc *entry = &ring->desc[ring->idx]; | ||
100 | struct sk_buff *skb = __skb_dequeue(&ring->queue); | ||
101 | |||
102 | pci_unmap_single(rtlpci->pdev, | ||
103 | rtlpriv->cfg->ops->get_desc( | ||
104 | (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), | ||
105 | skb->len, PCI_DMA_TODEVICE); | ||
106 | kfree_skb(skb); | ||
107 | ring->idx = (ring->idx + 1) % ring->entries; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static void _rtl88ee_disable_bcn_sub_func(struct ieee80211_hw *hw) | ||
112 | { | ||
113 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(1), 0); | ||
114 | } | ||
115 | |||
116 | static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw, | ||
117 | u8 rpwm_val, bool need_turn_off_ckk) | ||
118 | { | ||
119 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
120 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
121 | bool support_remote_wake_up; | ||
122 | u32 count = 0, isr_regaddr, content; | ||
123 | bool schedule_timer = need_turn_off_ckk; | ||
124 | |||
125 | rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, | ||
126 | (u8 *)(&support_remote_wake_up)); | ||
127 | if (!rtlhal->fw_ready) | ||
128 | return; | ||
129 | if (!rtlpriv->psc.fw_current_inpsmode) | ||
130 | return; | ||
131 | |||
132 | while (1) { | ||
133 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
134 | if (rtlhal->fw_clk_change_in_progress) { | ||
135 | while (rtlhal->fw_clk_change_in_progress) { | ||
136 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
137 | udelay(100); | ||
138 | if (++count > 1000) | ||
139 | return; | ||
140 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
141 | } | ||
142 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
143 | } else { | ||
144 | rtlhal->fw_clk_change_in_progress = false; | ||
145 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | if (IS_IN_LOW_POWER_STATE_88E(rtlhal->fw_ps_state)) { | ||
150 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, | ||
151 | (u8 *)(&rpwm_val)); | ||
152 | if (FW_PS_IS_ACK(rpwm_val)) { | ||
153 | isr_regaddr = REG_HISR; | ||
154 | content = rtl_read_dword(rtlpriv, isr_regaddr); | ||
155 | while (!(content & IMR_CPWM) && (count < 500)) { | ||
156 | udelay(50); | ||
157 | count++; | ||
158 | content = rtl_read_dword(rtlpriv, isr_regaddr); | ||
159 | } | ||
160 | |||
161 | if (content & IMR_CPWM) { | ||
162 | rtl_write_word(rtlpriv, isr_regaddr, 0x0100); | ||
163 | rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_88E; | ||
164 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
165 | "Receive CPWM INT!!! Set pHalData->FwPSState = %X\n", | ||
166 | rtlhal->fw_ps_state); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
171 | rtlhal->fw_clk_change_in_progress = false; | ||
172 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
173 | if (schedule_timer) { | ||
174 | mod_timer(&rtlpriv->works.fw_clockoff_timer, | ||
175 | jiffies + MSECS(10)); | ||
176 | } | ||
177 | } else { | ||
178 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
179 | rtlhal->fw_clk_change_in_progress = false; | ||
180 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static void _rtl88ee_set_fw_clock_off(struct ieee80211_hw *hw, | ||
185 | u8 rpwm_val) | ||
186 | { | ||
187 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
188 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
189 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
190 | struct rtl8192_tx_ring *ring; | ||
191 | enum rf_pwrstate rtstate; | ||
192 | bool schedule_timer = false; | ||
193 | u8 queue; | ||
194 | |||
195 | if (!rtlhal->fw_ready) | ||
196 | return; | ||
197 | if (!rtlpriv->psc.fw_current_inpsmode) | ||
198 | return; | ||
199 | if (!rtlhal->allow_sw_to_change_hwclc) | ||
200 | return; | ||
201 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); | ||
202 | if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) | ||
203 | return; | ||
204 | |||
205 | for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { | ||
206 | ring = &rtlpci->tx_ring[queue]; | ||
207 | if (skb_queue_len(&ring->queue)) { | ||
208 | schedule_timer = true; | ||
209 | break; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | if (schedule_timer) { | ||
214 | mod_timer(&rtlpriv->works.fw_clockoff_timer, | ||
215 | jiffies + MSECS(10)); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | if (FW_PS_STATE(rtlhal->fw_ps_state) != | ||
220 | FW_PS_STATE_RF_OFF_LOW_PWR_88E) { | ||
221 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
222 | if (!rtlhal->fw_clk_change_in_progress) { | ||
223 | rtlhal->fw_clk_change_in_progress = true; | ||
224 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
225 | rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); | ||
226 | rtl_write_word(rtlpriv, REG_HISR, 0x0100); | ||
227 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
228 | (u8 *)(&rpwm_val)); | ||
229 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
230 | rtlhal->fw_clk_change_in_progress = false; | ||
231 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
232 | } else { | ||
233 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
234 | mod_timer(&rtlpriv->works.fw_clockoff_timer, | ||
235 | jiffies + MSECS(10)); | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | static void _rtl88ee_set_fw_ps_rf_on(struct ieee80211_hw *hw) | ||
241 | { | ||
242 | u8 rpwm_val = 0; | ||
243 | |||
244 | rpwm_val |= (FW_PS_STATE_RF_OFF_88E | FW_PS_ACK); | ||
245 | _rtl88ee_set_fw_clock_on(hw, rpwm_val, true); | ||
246 | } | ||
247 | |||
248 | static void _rtl88ee_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw) | ||
249 | { | ||
250 | u8 rpwm_val = 0; | ||
251 | |||
252 | rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR_88E; | ||
253 | _rtl88ee_set_fw_clock_off(hw, rpwm_val); | ||
254 | } | ||
255 | |||
256 | void rtl88ee_fw_clk_off_timer_callback(unsigned long data) | ||
257 | { | ||
258 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
259 | |||
260 | _rtl88ee_set_fw_ps_rf_off_low_power(hw); | ||
261 | } | ||
262 | |||
263 | static void _rtl88ee_fwlps_leave(struct ieee80211_hw *hw) | ||
264 | { | ||
265 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
266 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
267 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
268 | bool fw_current_inps = false; | ||
269 | u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; | ||
270 | |||
271 | if (ppsc->low_power_enable) { | ||
272 | rpwm_val = (FW_PS_STATE_ALL_ON_88E|FW_PS_ACK);/* RF on */ | ||
273 | _rtl88ee_set_fw_clock_on(hw, rpwm_val, false); | ||
274 | rtlhal->allow_sw_to_change_hwclc = false; | ||
275 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
276 | (u8 *)(&fw_pwrmode)); | ||
277 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
278 | (u8 *)(&fw_current_inps)); | ||
279 | } else { | ||
280 | rpwm_val = FW_PS_STATE_ALL_ON_88E; /* RF on */ | ||
281 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
282 | (u8 *)(&rpwm_val)); | ||
283 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
284 | (u8 *)(&fw_pwrmode)); | ||
285 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
286 | (u8 *)(&fw_current_inps)); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | static void _rtl88ee_fwlps_enter(struct ieee80211_hw *hw) | ||
291 | { | ||
292 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
293 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
294 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
295 | bool fw_current_inps = true; | ||
296 | u8 rpwm_val; | ||
297 | |||
298 | if (ppsc->low_power_enable) { | ||
299 | rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_88E; /* RF off */ | ||
300 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
301 | (u8 *)(&fw_current_inps)); | ||
302 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
303 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
304 | rtlhal->allow_sw_to_change_hwclc = true; | ||
305 | _rtl88ee_set_fw_clock_off(hw, rpwm_val); | ||
306 | } else { | ||
307 | rpwm_val = FW_PS_STATE_RF_OFF_88E; /* RF off */ | ||
308 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
309 | (u8 *)(&fw_current_inps)); | ||
310 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
311 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
312 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
313 | (u8 *)(&rpwm_val)); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | ||
318 | { | ||
319 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
320 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
321 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
322 | |||
323 | switch (variable) { | ||
324 | case HW_VAR_RCR: | ||
325 | *((u32 *)(val)) = rtlpci->receive_config; | ||
326 | break; | ||
327 | case HW_VAR_RF_STATE: | ||
328 | *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; | ||
329 | break; | ||
330 | case HW_VAR_FWLPS_RF_ON:{ | ||
331 | enum rf_pwrstate rfstate; | ||
332 | u32 val_rcr; | ||
333 | |||
334 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, | ||
335 | (u8 *)(&rfstate)); | ||
336 | if (rfstate == ERFOFF) { | ||
337 | *((bool *)(val)) = true; | ||
338 | } else { | ||
339 | val_rcr = rtl_read_dword(rtlpriv, REG_RCR); | ||
340 | val_rcr &= 0x00070000; | ||
341 | if (val_rcr) | ||
342 | *((bool *)(val)) = false; | ||
343 | else | ||
344 | *((bool *)(val)) = true; | ||
345 | } | ||
346 | break; | ||
347 | } | ||
348 | case HW_VAR_FW_PSMODE_STATUS: | ||
349 | *((bool *)(val)) = ppsc->fw_current_inpsmode; | ||
350 | break; | ||
351 | case HW_VAR_CORRECT_TSF:{ | ||
352 | u64 tsf; | ||
353 | u32 *ptsf_low = (u32 *)&tsf; | ||
354 | u32 *ptsf_high = ((u32 *)&tsf) + 1; | ||
355 | |||
356 | *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); | ||
357 | *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); | ||
358 | |||
359 | *((u64 *)(val)) = tsf; | ||
360 | break; } | ||
361 | default: | ||
362 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
363 | "switch case not process %x\n", variable); | ||
364 | break; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | ||
369 | { | ||
370 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
371 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
372 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
373 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
374 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
375 | u8 idx; | ||
376 | |||
377 | switch (variable) { | ||
378 | case HW_VAR_ETHER_ADDR: | ||
379 | for (idx = 0; idx < ETH_ALEN; idx++) | ||
380 | rtl_write_byte(rtlpriv, (REG_MACID + idx), val[idx]); | ||
381 | break; | ||
382 | case HW_VAR_BASIC_RATE:{ | ||
383 | u16 rate_cfg = ((u16 *)val)[0]; | ||
384 | u8 rate_index = 0; | ||
385 | rate_cfg = rate_cfg & 0x15f; | ||
386 | rate_cfg |= 0x01; | ||
387 | rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); | ||
388 | rtl_write_byte(rtlpriv, REG_RRSR + 1, (rate_cfg >> 8) & 0xff); | ||
389 | while (rate_cfg > 0x1) { | ||
390 | rate_cfg = (rate_cfg >> 1); | ||
391 | rate_index++; | ||
392 | } | ||
393 | rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, rate_index); | ||
394 | break; } | ||
395 | case HW_VAR_BSSID: | ||
396 | for (idx = 0; idx < ETH_ALEN; idx++) | ||
397 | rtl_write_byte(rtlpriv, (REG_BSSID + idx), val[idx]); | ||
398 | break; | ||
399 | case HW_VAR_SIFS: | ||
400 | rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); | ||
401 | rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); | ||
402 | |||
403 | rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); | ||
404 | rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); | ||
405 | |||
406 | if (!mac->ht_enable) | ||
407 | rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, 0x0e0e); | ||
408 | else | ||
409 | rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, | ||
410 | *((u16 *)val)); | ||
411 | break; | ||
412 | case HW_VAR_SLOT_TIME:{ | ||
413 | u8 e_aci; | ||
414 | |||
415 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
416 | "HW_VAR_SLOT_TIME %x\n", val[0]); | ||
417 | |||
418 | rtl_write_byte(rtlpriv, REG_SLOT, val[0]); | ||
419 | |||
420 | for (e_aci = 0; e_aci < AC_MAX; e_aci++) { | ||
421 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, | ||
422 | (u8 *)(&e_aci)); | ||
423 | } | ||
424 | break; } | ||
425 | case HW_VAR_ACK_PREAMBLE:{ | ||
426 | u8 reg_tmp; | ||
427 | u8 short_preamble = (bool) (*(u8 *)val); | ||
428 | reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2); | ||
429 | if (short_preamble) { | ||
430 | reg_tmp |= 0x02; | ||
431 | rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); | ||
432 | } else { | ||
433 | reg_tmp |= 0xFD; | ||
434 | rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); | ||
435 | } | ||
436 | break; } | ||
437 | case HW_VAR_WPA_CONFIG: | ||
438 | rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); | ||
439 | break; | ||
440 | case HW_VAR_AMPDU_MIN_SPACE:{ | ||
441 | u8 min_spacing_to_set; | ||
442 | u8 sec_min_space; | ||
443 | |||
444 | min_spacing_to_set = *((u8 *)val); | ||
445 | if (min_spacing_to_set <= 7) { | ||
446 | sec_min_space = 0; | ||
447 | |||
448 | if (min_spacing_to_set < sec_min_space) | ||
449 | min_spacing_to_set = sec_min_space; | ||
450 | |||
451 | mac->min_space_cfg = ((mac->min_space_cfg & | ||
452 | 0xf8) | min_spacing_to_set); | ||
453 | |||
454 | *val = min_spacing_to_set; | ||
455 | |||
456 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
457 | "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", | ||
458 | mac->min_space_cfg); | ||
459 | |||
460 | rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, | ||
461 | mac->min_space_cfg); | ||
462 | } | ||
463 | break; } | ||
464 | case HW_VAR_SHORTGI_DENSITY:{ | ||
465 | u8 density_to_set; | ||
466 | |||
467 | density_to_set = *((u8 *)val); | ||
468 | mac->min_space_cfg |= (density_to_set << 3); | ||
469 | |||
470 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
471 | "Set HW_VAR_SHORTGI_DENSITY: %#x\n", | ||
472 | mac->min_space_cfg); | ||
473 | |||
474 | rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, | ||
475 | mac->min_space_cfg); | ||
476 | break; } | ||
477 | case HW_VAR_AMPDU_FACTOR:{ | ||
478 | u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; | ||
479 | u8 factor; | ||
480 | u8 *reg = NULL; | ||
481 | u8 id = 0; | ||
482 | |||
483 | reg = regtoset_normal; | ||
484 | |||
485 | factor = *((u8 *)val); | ||
486 | if (factor <= 3) { | ||
487 | factor = (1 << (factor + 2)); | ||
488 | if (factor > 0xf) | ||
489 | factor = 0xf; | ||
490 | |||
491 | for (id = 0; id < 4; id++) { | ||
492 | if ((reg[id] & 0xf0) > (factor << 4)) | ||
493 | reg[id] = (reg[id] & 0x0f) | | ||
494 | (factor << 4); | ||
495 | |||
496 | if ((reg[id] & 0x0f) > factor) | ||
497 | reg[id] = (reg[id] & 0xf0) | (factor); | ||
498 | |||
499 | rtl_write_byte(rtlpriv, (REG_AGGLEN_LMT + id), | ||
500 | reg[id]); | ||
501 | } | ||
502 | |||
503 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
504 | "Set HW_VAR_AMPDU_FACTOR: %#x\n", factor); | ||
505 | } | ||
506 | break; } | ||
507 | case HW_VAR_AC_PARAM:{ | ||
508 | u8 e_aci = *((u8 *)val); | ||
509 | rtl88e_dm_init_edca_turbo(hw); | ||
510 | |||
511 | if (rtlpci->acm_method != eAcmWay2_SW) | ||
512 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, | ||
513 | (u8 *)(&e_aci)); | ||
514 | break; } | ||
515 | case HW_VAR_ACM_CTRL:{ | ||
516 | u8 e_aci = *((u8 *)val); | ||
517 | union aci_aifsn *p_aci_aifsn = | ||
518 | (union aci_aifsn *)(&(mac->ac[0].aifs)); | ||
519 | u8 acm = p_aci_aifsn->f.acm; | ||
520 | u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); | ||
521 | |||
522 | acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); | ||
523 | |||
524 | if (acm) { | ||
525 | switch (e_aci) { | ||
526 | case AC0_BE: | ||
527 | acm_ctrl |= ACMHW_BEQEN; | ||
528 | break; | ||
529 | case AC2_VI: | ||
530 | acm_ctrl |= ACMHW_VIQEN; | ||
531 | break; | ||
532 | case AC3_VO: | ||
533 | acm_ctrl |= ACMHW_VOQEN; | ||
534 | break; | ||
535 | default: | ||
536 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
537 | "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", | ||
538 | acm); | ||
539 | break; | ||
540 | } | ||
541 | } else { | ||
542 | switch (e_aci) { | ||
543 | case AC0_BE: | ||
544 | acm_ctrl &= (~ACMHW_BEQEN); | ||
545 | break; | ||
546 | case AC2_VI: | ||
547 | acm_ctrl &= (~ACMHW_VIQEN); | ||
548 | break; | ||
549 | case AC3_VO: | ||
550 | acm_ctrl &= (~ACMHW_BEQEN); | ||
551 | break; | ||
552 | default: | ||
553 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
554 | "switch case not process\n"); | ||
555 | break; | ||
556 | } | ||
557 | } | ||
558 | |||
559 | RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, | ||
560 | "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", | ||
561 | acm_ctrl); | ||
562 | rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); | ||
563 | break; } | ||
564 | case HW_VAR_RCR: | ||
565 | rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); | ||
566 | rtlpci->receive_config = ((u32 *)(val))[0]; | ||
567 | break; | ||
568 | case HW_VAR_RETRY_LIMIT:{ | ||
569 | u8 retry_limit = ((u8 *)(val))[0]; | ||
570 | |||
571 | rtl_write_word(rtlpriv, REG_RL, | ||
572 | retry_limit << RETRY_LIMIT_SHORT_SHIFT | | ||
573 | retry_limit << RETRY_LIMIT_LONG_SHIFT); | ||
574 | break; } | ||
575 | case HW_VAR_DUAL_TSF_RST: | ||
576 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); | ||
577 | break; | ||
578 | case HW_VAR_EFUSE_BYTES: | ||
579 | rtlefuse->efuse_usedbytes = *((u16 *)val); | ||
580 | break; | ||
581 | case HW_VAR_EFUSE_USAGE: | ||
582 | rtlefuse->efuse_usedpercentage = *((u8 *)val); | ||
583 | break; | ||
584 | case HW_VAR_IO_CMD: | ||
585 | rtl88e_phy_set_io_cmd(hw, (*(enum io_type *)val)); | ||
586 | break; | ||
587 | case HW_VAR_SET_RPWM:{ | ||
588 | u8 rpwm_val; | ||
589 | |||
590 | rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); | ||
591 | udelay(1); | ||
592 | |||
593 | if (rpwm_val & BIT(7)) { | ||
594 | rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, | ||
595 | (*(u8 *)val)); | ||
596 | } else { | ||
597 | rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, | ||
598 | ((*(u8 *)val) | BIT(7))); | ||
599 | } | ||
600 | break; } | ||
601 | case HW_VAR_H2C_FW_PWRMODE: | ||
602 | rtl88e_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); | ||
603 | break; | ||
604 | case HW_VAR_FW_PSMODE_STATUS: | ||
605 | ppsc->fw_current_inpsmode = *((bool *)val); | ||
606 | break; | ||
607 | case HW_VAR_RESUME_CLK_ON: | ||
608 | _rtl88ee_set_fw_ps_rf_on(hw); | ||
609 | break; | ||
610 | case HW_VAR_FW_LPS_ACTION:{ | ||
611 | bool enter_fwlps = *((bool *)val); | ||
612 | |||
613 | if (enter_fwlps) | ||
614 | _rtl88ee_fwlps_enter(hw); | ||
615 | else | ||
616 | _rtl88ee_fwlps_leave(hw); | ||
617 | break; } | ||
618 | case HW_VAR_H2C_FW_JOINBSSRPT:{ | ||
619 | u8 mstatus = (*(u8 *)val); | ||
620 | u8 tmp, tmp_reg422, uval; | ||
621 | u8 count = 0, dlbcn_count = 0; | ||
622 | bool recover = false; | ||
623 | |||
624 | if (mstatus == RT_MEDIA_CONNECT) { | ||
625 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); | ||
626 | |||
627 | tmp = rtl_read_byte(rtlpriv, REG_CR + 1); | ||
628 | rtl_write_byte(rtlpriv, REG_CR + 1, (tmp | BIT(0))); | ||
629 | |||
630 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); | ||
631 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
632 | |||
633 | tmp_reg422 = rtl_read_byte(rtlpriv, | ||
634 | REG_FWHW_TXQ_CTRL + 2); | ||
635 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, | ||
636 | tmp_reg422 & (~BIT(6))); | ||
637 | if (tmp_reg422 & BIT(6)) | ||
638 | recover = true; | ||
639 | |||
640 | do { | ||
641 | uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2); | ||
642 | rtl_write_byte(rtlpriv, REG_TDECTRL+2, | ||
643 | (uval | BIT(0))); | ||
644 | _rtl88ee_return_beacon_queue_skb(hw); | ||
645 | |||
646 | rtl88e_set_fw_rsvdpagepkt(hw, 0); | ||
647 | uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2); | ||
648 | count = 0; | ||
649 | while (!(uval & BIT(0)) && count < 20) { | ||
650 | count++; | ||
651 | udelay(10); | ||
652 | uval = rtl_read_byte(rtlpriv, | ||
653 | REG_TDECTRL+2); | ||
654 | } | ||
655 | dlbcn_count++; | ||
656 | } while (!(uval & BIT(0)) && dlbcn_count < 5); | ||
657 | |||
658 | if (uval & BIT(0)) | ||
659 | rtl_write_byte(rtlpriv, REG_TDECTRL+2, BIT(0)); | ||
660 | |||
661 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); | ||
662 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); | ||
663 | |||
664 | if (recover) { | ||
665 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, | ||
666 | tmp_reg422); | ||
667 | } | ||
668 | rtl_write_byte(rtlpriv, REG_CR + 1, (tmp & ~(BIT(0)))); | ||
669 | } | ||
670 | rtl88e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val)); | ||
671 | break; } | ||
672 | case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: | ||
673 | rtl88e_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); | ||
674 | break; | ||
675 | case HW_VAR_AID:{ | ||
676 | u16 u2btmp; | ||
677 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); | ||
678 | u2btmp &= 0xC000; | ||
679 | rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | | ||
680 | mac->assoc_id)); | ||
681 | break; } | ||
682 | case HW_VAR_CORRECT_TSF:{ | ||
683 | u8 btype_ibss = ((u8 *)(val))[0]; | ||
684 | |||
685 | if (btype_ibss == true) | ||
686 | _rtl88ee_stop_tx_beacon(hw); | ||
687 | |||
688 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); | ||
689 | |||
690 | rtl_write_dword(rtlpriv, REG_TSFTR, | ||
691 | (u32) (mac->tsf & 0xffffffff)); | ||
692 | rtl_write_dword(rtlpriv, REG_TSFTR + 4, | ||
693 | (u32) ((mac->tsf >> 32) & 0xffffffff)); | ||
694 | |||
695 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); | ||
696 | |||
697 | if (btype_ibss == true) | ||
698 | _rtl88ee_resume_tx_beacon(hw); | ||
699 | break; } | ||
700 | default: | ||
701 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
702 | "switch case not process %x\n", variable); | ||
703 | break; | ||
704 | } | ||
705 | } | ||
706 | |||
707 | static bool _rtl88ee_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) | ||
708 | { | ||
709 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
710 | bool status = true; | ||
711 | long count = 0; | ||
712 | u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | | ||
713 | _LLT_OP(_LLT_WRITE_ACCESS); | ||
714 | |||
715 | rtl_write_dword(rtlpriv, REG_LLT_INIT, value); | ||
716 | |||
717 | do { | ||
718 | value = rtl_read_dword(rtlpriv, REG_LLT_INIT); | ||
719 | if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) | ||
720 | break; | ||
721 | |||
722 | if (count > POLLING_LLT_THRESHOLD) { | ||
723 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
724 | "Failed to polling write LLT done at address %d!\n", | ||
725 | address); | ||
726 | status = false; | ||
727 | break; | ||
728 | } | ||
729 | } while (++count); | ||
730 | |||
731 | return status; | ||
732 | } | ||
733 | |||
734 | static bool _rtl88ee_llt_table_init(struct ieee80211_hw *hw) | ||
735 | { | ||
736 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
737 | unsigned short i; | ||
738 | u8 txpktbuf_bndy; | ||
739 | u8 maxpage; | ||
740 | bool status; | ||
741 | |||
742 | maxpage = 0xAF; | ||
743 | txpktbuf_bndy = 0xAB; | ||
744 | |||
745 | rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x01); | ||
746 | rtl_write_dword(rtlpriv, REG_RQPN, 0x80730d29); | ||
747 | |||
748 | |||
749 | rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x25FF0000 | txpktbuf_bndy)); | ||
750 | rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); | ||
751 | |||
752 | rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); | ||
753 | rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); | ||
754 | |||
755 | rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); | ||
756 | rtl_write_byte(rtlpriv, REG_PBP, 0x11); | ||
757 | rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); | ||
758 | |||
759 | for (i = 0; i < (txpktbuf_bndy - 1); i++) { | ||
760 | status = _rtl88ee_llt_write(hw, i, i + 1); | ||
761 | if (true != status) | ||
762 | return status; | ||
763 | } | ||
764 | |||
765 | status = _rtl88ee_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); | ||
766 | if (true != status) | ||
767 | return status; | ||
768 | |||
769 | for (i = txpktbuf_bndy; i < maxpage; i++) { | ||
770 | status = _rtl88ee_llt_write(hw, i, (i + 1)); | ||
771 | if (true != status) | ||
772 | return status; | ||
773 | } | ||
774 | |||
775 | status = _rtl88ee_llt_write(hw, maxpage, txpktbuf_bndy); | ||
776 | if (true != status) | ||
777 | return status; | ||
778 | |||
779 | return true; | ||
780 | } | ||
781 | |||
782 | static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw) | ||
783 | { | ||
784 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
785 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
786 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
787 | struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); | ||
788 | |||
789 | if (rtlpriv->rtlhal.up_first_time) | ||
790 | return; | ||
791 | |||
792 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) | ||
793 | rtl88ee_sw_led_on(hw, pLed0); | ||
794 | else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) | ||
795 | rtl88ee_sw_led_on(hw, pLed0); | ||
796 | else | ||
797 | rtl88ee_sw_led_off(hw, pLed0); | ||
798 | } | ||
799 | |||
800 | static bool _rtl88ee_init_mac(struct ieee80211_hw *hw) | ||
801 | { | ||
802 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
803 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
804 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
805 | u8 bytetmp; | ||
806 | u16 wordtmp; | ||
807 | |||
808 | /*Disable XTAL OUTPUT for power saving. YJ, add, 111206. */ | ||
809 | bytetmp = rtl_read_byte(rtlpriv, REG_XCK_OUT_CTRL) & (~BIT(0)); | ||
810 | rtl_write_byte(rtlpriv, REG_XCK_OUT_CTRL, bytetmp); | ||
811 | /*Auto Power Down to CHIP-off State*/ | ||
812 | bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); | ||
813 | rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); | ||
814 | |||
815 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); | ||
816 | /* HW Power on sequence */ | ||
817 | if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, | ||
818 | PWR_INTF_PCI_MSK, | ||
819 | Rtl8188E_NIC_ENABLE_FLOW)) { | ||
820 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
821 | "init MAC Fail as rtl_hal_pwrseqcmdparsing\n"); | ||
822 | return false; | ||
823 | } | ||
824 | |||
825 | bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); | ||
826 | rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); | ||
827 | |||
828 | bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2); | ||
829 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp|BIT(2)); | ||
830 | |||
831 | bytetmp = rtl_read_byte(rtlpriv, REG_WATCH_DOG+1); | ||
832 | rtl_write_byte(rtlpriv, REG_WATCH_DOG+1, bytetmp|BIT(7)); | ||
833 | |||
834 | bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1); | ||
835 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1, bytetmp|BIT(1)); | ||
836 | |||
837 | bytetmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); | ||
838 | rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, bytetmp|BIT(1)|BIT(0)); | ||
839 | rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL+1, 2); | ||
840 | rtl_write_word(rtlpriv, REG_TX_RPT_TIME, 0xcdf0); | ||
841 | |||
842 | /*Add for wake up online*/ | ||
843 | bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); | ||
844 | |||
845 | rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp|BIT(3)); | ||
846 | bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG+1); | ||
847 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+1, (bytetmp & (~BIT(4)))); | ||
848 | rtl_write_byte(rtlpriv, 0x367, 0x80); | ||
849 | |||
850 | rtl_write_word(rtlpriv, REG_CR, 0x2ff); | ||
851 | rtl_write_byte(rtlpriv, REG_CR+1, 0x06); | ||
852 | rtl_write_byte(rtlpriv, REG_CR+2, 0x00); | ||
853 | |||
854 | if (!rtlhal->mac_func_enable) { | ||
855 | if (_rtl88ee_llt_table_init(hw) == false) { | ||
856 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
857 | "LLT table init fail\n"); | ||
858 | return false; | ||
859 | } | ||
860 | } | ||
861 | |||
862 | |||
863 | rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); | ||
864 | rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); | ||
865 | |||
866 | wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); | ||
867 | wordtmp &= 0xf; | ||
868 | wordtmp |= 0xE771; | ||
869 | rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); | ||
870 | |||
871 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
872 | rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xffff); | ||
873 | rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); | ||
874 | |||
875 | rtl_write_dword(rtlpriv, REG_BCNQ_DESA, | ||
876 | ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & | ||
877 | DMA_BIT_MASK(32)); | ||
878 | rtl_write_dword(rtlpriv, REG_MGQ_DESA, | ||
879 | (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & | ||
880 | DMA_BIT_MASK(32)); | ||
881 | rtl_write_dword(rtlpriv, REG_VOQ_DESA, | ||
882 | (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); | ||
883 | rtl_write_dword(rtlpriv, REG_VIQ_DESA, | ||
884 | (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); | ||
885 | rtl_write_dword(rtlpriv, REG_BEQ_DESA, | ||
886 | (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); | ||
887 | rtl_write_dword(rtlpriv, REG_BKQ_DESA, | ||
888 | (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); | ||
889 | rtl_write_dword(rtlpriv, REG_HQ_DESA, | ||
890 | (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & | ||
891 | DMA_BIT_MASK(32)); | ||
892 | rtl_write_dword(rtlpriv, REG_RX_DESA, | ||
893 | (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & | ||
894 | DMA_BIT_MASK(32)); | ||
895 | |||
896 | /* if we want to support 64 bit DMA, we should set it here, | ||
897 | * but at the moment we do not support 64 bit DMA | ||
898 | */ | ||
899 | |||
900 | rtl_write_dword(rtlpriv, REG_INT_MIG, 0); | ||
901 | |||
902 | rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); | ||
903 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0);/*Enable RX DMA */ | ||
904 | |||
905 | if (rtlhal->earlymode_enable) {/*Early mode enable*/ | ||
906 | bytetmp = rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL); | ||
907 | bytetmp |= 0x1f; | ||
908 | rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, bytetmp); | ||
909 | rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL+3, 0x81); | ||
910 | } | ||
911 | _rtl88ee_gen_refresh_led_state(hw); | ||
912 | return true; | ||
913 | } | ||
914 | |||
915 | static void _rtl88ee_hw_configure(struct ieee80211_hw *hw) | ||
916 | { | ||
917 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
918 | u32 reg_prsr; | ||
919 | |||
920 | reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; | ||
921 | |||
922 | rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); | ||
923 | rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); | ||
924 | } | ||
925 | |||
926 | static void _rtl88ee_enable_aspm_back_door(struct ieee80211_hw *hw) | ||
927 | { | ||
928 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
929 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
930 | u8 tmp1byte = 0; | ||
931 | u32 tmp4Byte = 0, count; | ||
932 | |||
933 | rtl_write_word(rtlpriv, 0x354, 0x8104); | ||
934 | rtl_write_word(rtlpriv, 0x358, 0x24); | ||
935 | |||
936 | rtl_write_word(rtlpriv, 0x350, 0x70c); | ||
937 | rtl_write_byte(rtlpriv, 0x352, 0x2); | ||
938 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
939 | count = 0; | ||
940 | while (tmp1byte && count < 20) { | ||
941 | udelay(10); | ||
942 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
943 | count++; | ||
944 | } | ||
945 | if (0 == tmp1byte) { | ||
946 | tmp4Byte = rtl_read_dword(rtlpriv, 0x34c); | ||
947 | rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(31)); | ||
948 | rtl_write_word(rtlpriv, 0x350, 0xf70c); | ||
949 | rtl_write_byte(rtlpriv, 0x352, 0x1); | ||
950 | } | ||
951 | |||
952 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
953 | count = 0; | ||
954 | while (tmp1byte && count < 20) { | ||
955 | udelay(10); | ||
956 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
957 | count++; | ||
958 | } | ||
959 | |||
960 | rtl_write_word(rtlpriv, 0x350, 0x718); | ||
961 | rtl_write_byte(rtlpriv, 0x352, 0x2); | ||
962 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
963 | count = 0; | ||
964 | while (tmp1byte && count < 20) { | ||
965 | udelay(10); | ||
966 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
967 | count++; | ||
968 | } | ||
969 | if (ppsc->support_backdoor || (0 == tmp1byte)) { | ||
970 | tmp4Byte = rtl_read_dword(rtlpriv, 0x34c); | ||
971 | rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(11)|BIT(12)); | ||
972 | rtl_write_word(rtlpriv, 0x350, 0xf718); | ||
973 | rtl_write_byte(rtlpriv, 0x352, 0x1); | ||
974 | } | ||
975 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
976 | count = 0; | ||
977 | while (tmp1byte && count < 20) { | ||
978 | udelay(10); | ||
979 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
980 | count++; | ||
981 | } | ||
982 | } | ||
983 | |||
984 | void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw) | ||
985 | { | ||
986 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
987 | u8 sec_reg_value; | ||
988 | |||
989 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
990 | "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", | ||
991 | rtlpriv->sec.pairwise_enc_algorithm, | ||
992 | rtlpriv->sec.group_enc_algorithm); | ||
993 | |||
994 | if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { | ||
995 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
996 | "not open hw encryption\n"); | ||
997 | return; | ||
998 | } | ||
999 | sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; | ||
1000 | |||
1001 | if (rtlpriv->sec.use_defaultkey) { | ||
1002 | sec_reg_value |= SCR_TXUSEDK; | ||
1003 | sec_reg_value |= SCR_RXUSEDK; | ||
1004 | } | ||
1005 | |||
1006 | sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); | ||
1007 | |||
1008 | rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); | ||
1009 | |||
1010 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
1011 | "The SECR-value %x\n", sec_reg_value); | ||
1012 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); | ||
1013 | } | ||
1014 | |||
1015 | int rtl88ee_hw_init(struct ieee80211_hw *hw) | ||
1016 | { | ||
1017 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1018 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1019 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1020 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1021 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1022 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1023 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1024 | bool rtstatus = true; | ||
1025 | int err = 0; | ||
1026 | u8 tmp_u1b, u1byte; | ||
1027 | |||
1028 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Rtl8188EE hw init\n"); | ||
1029 | rtlpriv->rtlhal.being_init_adapter = true; | ||
1030 | rtlpriv->intf_ops->disable_aspm(hw); | ||
1031 | |||
1032 | tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1); | ||
1033 | u1byte = rtl_read_byte(rtlpriv, REG_CR); | ||
1034 | if ((tmp_u1b & BIT(3)) && (u1byte != 0 && u1byte != 0xEA)) { | ||
1035 | rtlhal->mac_func_enable = true; | ||
1036 | } else { | ||
1037 | rtlhal->mac_func_enable = false; | ||
1038 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; | ||
1039 | } | ||
1040 | |||
1041 | rtstatus = _rtl88ee_init_mac(hw); | ||
1042 | if (rtstatus != true) { | ||
1043 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); | ||
1044 | err = 1; | ||
1045 | return err; | ||
1046 | } | ||
1047 | |||
1048 | err = rtl88e_download_fw(hw, false); | ||
1049 | if (err) { | ||
1050 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1051 | "Failed to download FW. Init HW without FW now..\n"); | ||
1052 | err = 1; | ||
1053 | rtlhal->fw_ready = false; | ||
1054 | return err; | ||
1055 | } else { | ||
1056 | rtlhal->fw_ready = true; | ||
1057 | } | ||
1058 | /*fw related variable initialize */ | ||
1059 | rtlhal->last_hmeboxnum = 0; | ||
1060 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; | ||
1061 | rtlhal->fw_clk_change_in_progress = false; | ||
1062 | rtlhal->allow_sw_to_change_hwclc = false; | ||
1063 | ppsc->fw_current_inpsmode = false; | ||
1064 | |||
1065 | rtl88e_phy_mac_config(hw); | ||
1066 | /* because last function modifies RCR, we update | ||
1067 | * rcr var here, or TP will be unstable for receive_config | ||
1068 | * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx | ||
1069 | * RCR_APP_ICV will cause mac80211 disassoc for cisco 1252 | ||
1070 | */ | ||
1071 | rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); | ||
1072 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
1073 | |||
1074 | rtl88e_phy_bb_config(hw); | ||
1075 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); | ||
1076 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); | ||
1077 | |||
1078 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; | ||
1079 | rtl88e_phy_rf_config(hw); | ||
1080 | |||
1081 | rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, | ||
1082 | RF_CHNLBW, RFREG_OFFSET_MASK); | ||
1083 | rtlphy->rfreg_chnlval[0] = rtlphy->rfreg_chnlval[0] & 0xfff00fff; | ||
1084 | |||
1085 | _rtl88ee_hw_configure(hw); | ||
1086 | rtl_cam_reset_all_entry(hw); | ||
1087 | rtl88ee_enable_hw_security_config(hw); | ||
1088 | |||
1089 | rtlhal->mac_func_enable = true; | ||
1090 | ppsc->rfpwr_state = ERFON; | ||
1091 | |||
1092 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); | ||
1093 | _rtl88ee_enable_aspm_back_door(hw); | ||
1094 | rtlpriv->intf_ops->enable_aspm(hw); | ||
1095 | |||
1096 | if (ppsc->rfpwr_state == ERFON) { | ||
1097 | if ((rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) || | ||
1098 | ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) && | ||
1099 | (rtlhal->oem_id == RT_CID_819x_HP))) { | ||
1100 | rtl88e_phy_set_rfpath_switch(hw, true); | ||
1101 | rtlpriv->dm.fat_table.rx_idle_ant = MAIN_ANT; | ||
1102 | } else { | ||
1103 | rtl88e_phy_set_rfpath_switch(hw, false); | ||
1104 | rtlpriv->dm.fat_table.rx_idle_ant = AUX_ANT; | ||
1105 | } | ||
1106 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1107 | "rx idle ant %s\n", | ||
1108 | (rtlpriv->dm.fat_table.rx_idle_ant == MAIN_ANT) ? | ||
1109 | ("MAIN_ANT") : ("AUX_ANT")); | ||
1110 | |||
1111 | if (rtlphy->iqk_initialized) { | ||
1112 | rtl88e_phy_iq_calibrate(hw, true); | ||
1113 | } else { | ||
1114 | rtl88e_phy_iq_calibrate(hw, false); | ||
1115 | rtlphy->iqk_initialized = true; | ||
1116 | } | ||
1117 | rtl88e_dm_check_txpower_tracking(hw); | ||
1118 | rtl88e_phy_lc_calibrate(hw); | ||
1119 | } | ||
1120 | |||
1121 | tmp_u1b = efuse_read_1byte(hw, 0x1FA); | ||
1122 | if (!(tmp_u1b & BIT(0))) { | ||
1123 | rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); | ||
1124 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path A\n"); | ||
1125 | } | ||
1126 | |||
1127 | if (!(tmp_u1b & BIT(4))) { | ||
1128 | tmp_u1b = rtl_read_byte(rtlpriv, 0x16); | ||
1129 | tmp_u1b &= 0x0F; | ||
1130 | rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); | ||
1131 | udelay(10); | ||
1132 | rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); | ||
1133 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "under 1.5V\n"); | ||
1134 | } | ||
1135 | rtl_write_byte(rtlpriv, REG_NAV_CTRL+2, ((30000+127)/128)); | ||
1136 | rtl88e_dm_init(hw); | ||
1137 | rtlpriv->rtlhal.being_init_adapter = false; | ||
1138 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "end of Rtl8188EE hw init %x\n", | ||
1139 | err); | ||
1140 | return 0; | ||
1141 | } | ||
1142 | |||
1143 | static enum version_8188e _rtl88ee_read_chip_version(struct ieee80211_hw *hw) | ||
1144 | { | ||
1145 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1146 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1147 | enum version_8188e version = VERSION_UNKNOWN; | ||
1148 | u32 value32; | ||
1149 | |||
1150 | value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); | ||
1151 | if (value32 & TRP_VAUX_EN) { | ||
1152 | version = (enum version_8188e) VERSION_TEST_CHIP_88E; | ||
1153 | } else { | ||
1154 | version = NORMAL_CHIP; | ||
1155 | version = version | ((value32 & TYPE_ID) ? RF_TYPE_2T2R : 0); | ||
1156 | version = version | ((value32 & VENDOR_ID) ? | ||
1157 | CHIP_VENDOR_UMC : 0); | ||
1158 | } | ||
1159 | |||
1160 | rtlphy->rf_type = RF_1T1R; | ||
1161 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1162 | "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? | ||
1163 | "RF_2T2R" : "RF_1T1R"); | ||
1164 | |||
1165 | return version; | ||
1166 | } | ||
1167 | |||
1168 | static int _rtl88ee_set_media_status(struct ieee80211_hw *hw, | ||
1169 | enum nl80211_iftype type) | ||
1170 | { | ||
1171 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1172 | u8 bt_msr = rtl_read_byte(rtlpriv, MSR); | ||
1173 | enum led_ctl_mode ledaction = LED_CTL_NO_LINK; | ||
1174 | bt_msr &= 0xfc; | ||
1175 | |||
1176 | if (type == NL80211_IFTYPE_UNSPECIFIED || | ||
1177 | type == NL80211_IFTYPE_STATION) { | ||
1178 | _rtl88ee_stop_tx_beacon(hw); | ||
1179 | _rtl88ee_enable_bcn_sub_func(hw); | ||
1180 | } else if (type == NL80211_IFTYPE_ADHOC || | ||
1181 | type == NL80211_IFTYPE_AP || | ||
1182 | type == NL80211_IFTYPE_MESH_POINT) { | ||
1183 | _rtl88ee_resume_tx_beacon(hw); | ||
1184 | _rtl88ee_disable_bcn_sub_func(hw); | ||
1185 | } else { | ||
1186 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1187 | "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", | ||
1188 | type); | ||
1189 | } | ||
1190 | |||
1191 | switch (type) { | ||
1192 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1193 | bt_msr |= MSR_NOLINK; | ||
1194 | ledaction = LED_CTL_LINK; | ||
1195 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1196 | "Set Network type to NO LINK!\n"); | ||
1197 | break; | ||
1198 | case NL80211_IFTYPE_ADHOC: | ||
1199 | bt_msr |= MSR_ADHOC; | ||
1200 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1201 | "Set Network type to Ad Hoc!\n"); | ||
1202 | break; | ||
1203 | case NL80211_IFTYPE_STATION: | ||
1204 | bt_msr |= MSR_INFRA; | ||
1205 | ledaction = LED_CTL_LINK; | ||
1206 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1207 | "Set Network type to STA!\n"); | ||
1208 | break; | ||
1209 | case NL80211_IFTYPE_AP: | ||
1210 | bt_msr |= MSR_AP; | ||
1211 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1212 | "Set Network type to AP!\n"); | ||
1213 | break; | ||
1214 | case NL80211_IFTYPE_MESH_POINT: | ||
1215 | bt_msr |= MSR_ADHOC; | ||
1216 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1217 | "Set Network type to Mesh Point!\n"); | ||
1218 | break; | ||
1219 | default: | ||
1220 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1221 | "Network type %d not support!\n", type); | ||
1222 | return 1; | ||
1223 | } | ||
1224 | |||
1225 | rtl_write_byte(rtlpriv, (MSR), bt_msr); | ||
1226 | rtlpriv->cfg->ops->led_control(hw, ledaction); | ||
1227 | if ((bt_msr & 0xfc) == MSR_AP) | ||
1228 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | ||
1229 | else | ||
1230 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); | ||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
1234 | void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | ||
1235 | { | ||
1236 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1237 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1238 | u32 reg_rcr = rtlpci->receive_config; | ||
1239 | |||
1240 | if (rtlpriv->psc.rfpwr_state != ERFON) | ||
1241 | return; | ||
1242 | |||
1243 | if (check_bssid == true) { | ||
1244 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); | ||
1245 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | ||
1246 | (u8 *)(®_rcr)); | ||
1247 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); | ||
1248 | } else if (check_bssid == false) { | ||
1249 | reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); | ||
1250 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
1251 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1252 | HW_VAR_RCR, (u8 *)(®_rcr)); | ||
1253 | } | ||
1254 | } | ||
1255 | |||
1256 | int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | ||
1257 | { | ||
1258 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1259 | |||
1260 | if (_rtl88ee_set_media_status(hw, type)) | ||
1261 | return -EOPNOTSUPP; | ||
1262 | |||
1263 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { | ||
1264 | if (type != NL80211_IFTYPE_AP && | ||
1265 | type != NL80211_IFTYPE_MESH_POINT) | ||
1266 | rtl88ee_set_check_bssid(hw, true); | ||
1267 | } else { | ||
1268 | rtl88ee_set_check_bssid(hw, false); | ||
1269 | } | ||
1270 | |||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1274 | /* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ | ||
1275 | void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci) | ||
1276 | { | ||
1277 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1278 | rtl88e_dm_init_edca_turbo(hw); | ||
1279 | switch (aci) { | ||
1280 | case AC1_BK: | ||
1281 | rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); | ||
1282 | break; | ||
1283 | case AC0_BE: | ||
1284 | break; | ||
1285 | case AC2_VI: | ||
1286 | rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); | ||
1287 | break; | ||
1288 | case AC3_VO: | ||
1289 | rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); | ||
1290 | break; | ||
1291 | default: | ||
1292 | RT_ASSERT(false, "invalid aci: %d !\n", aci); | ||
1293 | break; | ||
1294 | } | ||
1295 | } | ||
1296 | |||
1297 | void rtl88ee_enable_interrupt(struct ieee80211_hw *hw) | ||
1298 | { | ||
1299 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1300 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1301 | |||
1302 | rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); | ||
1303 | rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); | ||
1304 | rtlpci->irq_enabled = true; | ||
1305 | /* there are some C2H CMDs have been sent before system interrupt | ||
1306 | * is enabled, e.g., C2H, CPWM. | ||
1307 | * So we need to clear all C2H events that FW has notified, otherwise | ||
1308 | * FW won't schedule any commands anymore. | ||
1309 | */ | ||
1310 | rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0); | ||
1311 | /*enable system interrupt*/ | ||
1312 | rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF); | ||
1313 | } | ||
1314 | |||
1315 | void rtl88ee_disable_interrupt(struct ieee80211_hw *hw) | ||
1316 | { | ||
1317 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1318 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1319 | |||
1320 | rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); | ||
1321 | rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); | ||
1322 | rtlpci->irq_enabled = false; | ||
1323 | synchronize_irq(rtlpci->pdev->irq); | ||
1324 | } | ||
1325 | |||
1326 | static void _rtl88ee_poweroff_adapter(struct ieee80211_hw *hw) | ||
1327 | { | ||
1328 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1329 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1330 | u8 u1b_tmp; | ||
1331 | u32 count = 0; | ||
1332 | rtlhal->mac_func_enable = false; | ||
1333 | rtlpriv->intf_ops->enable_aspm(hw); | ||
1334 | |||
1335 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "POWER OFF adapter\n"); | ||
1336 | u1b_tmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); | ||
1337 | rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, u1b_tmp & (~BIT(1))); | ||
1338 | |||
1339 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
1340 | while (!(u1b_tmp & BIT(1)) && (count++ < 100)) { | ||
1341 | udelay(10); | ||
1342 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
1343 | count++; | ||
1344 | } | ||
1345 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0xFF); | ||
1346 | |||
1347 | rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, | ||
1348 | PWR_INTF_PCI_MSK, Rtl8188E_NIC_LPS_ENTER_FLOW); | ||
1349 | |||
1350 | rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); | ||
1351 | |||
1352 | if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready) | ||
1353 | rtl88e_firmware_selfreset(hw); | ||
1354 | |||
1355 | u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); | ||
1356 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); | ||
1357 | rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); | ||
1358 | |||
1359 | u1b_tmp = rtl_read_byte(rtlpriv, REG_32K_CTRL); | ||
1360 | rtl_write_byte(rtlpriv, REG_32K_CTRL, (u1b_tmp & (~BIT(0)))); | ||
1361 | |||
1362 | rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, | ||
1363 | PWR_INTF_PCI_MSK, Rtl8188E_NIC_DISABLE_FLOW); | ||
1364 | |||
1365 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); | ||
1366 | rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(3)))); | ||
1367 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); | ||
1368 | rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(3))); | ||
1369 | |||
1370 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); | ||
1371 | |||
1372 | u1b_tmp = rtl_read_byte(rtlpriv, GPIO_IN); | ||
1373 | rtl_write_byte(rtlpriv, GPIO_OUT, u1b_tmp); | ||
1374 | rtl_write_byte(rtlpriv, GPIO_IO_SEL, 0x7F); | ||
1375 | |||
1376 | u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); | ||
1377 | rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL, (u1b_tmp << 4) | u1b_tmp); | ||
1378 | u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL+1); | ||
1379 | rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL+1, u1b_tmp | 0x0F); | ||
1380 | |||
1381 | rtl_write_dword(rtlpriv, REG_GPIO_IO_SEL_2+2, 0x00080808); | ||
1382 | } | ||
1383 | |||
1384 | void rtl88ee_card_disable(struct ieee80211_hw *hw) | ||
1385 | { | ||
1386 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1387 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1388 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1389 | enum nl80211_iftype opmode; | ||
1390 | |||
1391 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8188ee card disable\n"); | ||
1392 | |||
1393 | mac->link_state = MAC80211_NOLINK; | ||
1394 | opmode = NL80211_IFTYPE_UNSPECIFIED; | ||
1395 | |||
1396 | _rtl88ee_set_media_status(hw, opmode); | ||
1397 | |||
1398 | if (rtlpriv->rtlhal.driver_is_goingto_unload || | ||
1399 | ppsc->rfoff_reason > RF_CHANGE_BY_PS) | ||
1400 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); | ||
1401 | |||
1402 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
1403 | _rtl88ee_poweroff_adapter(hw); | ||
1404 | |||
1405 | /* after power off we should do iqk again */ | ||
1406 | rtlpriv->phy.iqk_initialized = false; | ||
1407 | } | ||
1408 | |||
1409 | void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw, | ||
1410 | u32 *p_inta, u32 *p_intb) | ||
1411 | { | ||
1412 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1413 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1414 | |||
1415 | *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; | ||
1416 | rtl_write_dword(rtlpriv, ISR, *p_inta); | ||
1417 | |||
1418 | *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; | ||
1419 | rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); | ||
1420 | } | ||
1421 | |||
1422 | void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw) | ||
1423 | { | ||
1424 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1425 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1426 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1427 | u16 bcn_interval, atim_window; | ||
1428 | |||
1429 | bcn_interval = mac->beacon_interval; | ||
1430 | atim_window = 2; /*FIX MERGE */ | ||
1431 | rtl88ee_disable_interrupt(hw); | ||
1432 | rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); | ||
1433 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); | ||
1434 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); | ||
1435 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); | ||
1436 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); | ||
1437 | rtl_write_byte(rtlpriv, 0x606, 0x30); | ||
1438 | rtlpci->reg_bcn_ctrl_val |= BIT(3); | ||
1439 | rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); | ||
1440 | /*rtl88ee_enable_interrupt(hw);*/ | ||
1441 | } | ||
1442 | |||
1443 | void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw) | ||
1444 | { | ||
1445 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1446 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1447 | u16 bcn_interval = mac->beacon_interval; | ||
1448 | |||
1449 | RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, | ||
1450 | "beacon_interval:%d\n", bcn_interval); | ||
1451 | /*rtl88ee_disable_interrupt(hw);*/ | ||
1452 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); | ||
1453 | /*rtl88ee_enable_interrupt(hw);*/ | ||
1454 | } | ||
1455 | |||
1456 | void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw, | ||
1457 | u32 add_msr, u32 rm_msr) | ||
1458 | { | ||
1459 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1460 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1461 | |||
1462 | RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, | ||
1463 | "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); | ||
1464 | |||
1465 | rtl88ee_disable_interrupt(hw); | ||
1466 | if (add_msr) | ||
1467 | rtlpci->irq_mask[0] |= add_msr; | ||
1468 | if (rm_msr) | ||
1469 | rtlpci->irq_mask[0] &= (~rm_msr); | ||
1470 | rtl88ee_enable_interrupt(hw); | ||
1471 | } | ||
1472 | |||
1473 | static inline u8 get_chnl_group(u8 chnl) | ||
1474 | { | ||
1475 | u8 group; | ||
1476 | |||
1477 | group = chnl / 3; | ||
1478 | if (chnl == 14) | ||
1479 | group = 5; | ||
1480 | |||
1481 | return group; | ||
1482 | } | ||
1483 | |||
1484 | static void set_diff0_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path, | ||
1485 | u32 i, u32 eadr) | ||
1486 | { | ||
1487 | pwr2g->bw40_diff[path][i] = 0; | ||
1488 | if (hwinfo[eadr] == 0xFF) { | ||
1489 | pwr2g->bw20_diff[path][i] = 0x02; | ||
1490 | } else { | ||
1491 | pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1492 | /*bit sign number to 8 bit sign number*/ | ||
1493 | if (pwr2g->bw20_diff[path][i] & BIT(3)) | ||
1494 | pwr2g->bw20_diff[path][i] |= 0xF0; | ||
1495 | } | ||
1496 | |||
1497 | if (hwinfo[eadr] == 0xFF) { | ||
1498 | pwr2g->ofdm_diff[path][i] = 0x04; | ||
1499 | } else { | ||
1500 | pwr2g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f); | ||
1501 | /*bit sign number to 8 bit sign number*/ | ||
1502 | if (pwr2g->ofdm_diff[path][i] & BIT(3)) | ||
1503 | pwr2g->ofdm_diff[path][i] |= 0xF0; | ||
1504 | } | ||
1505 | pwr2g->cck_diff[path][i] = 0; | ||
1506 | } | ||
1507 | |||
1508 | static void set_diff0_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path, | ||
1509 | u32 i, u32 eadr) | ||
1510 | { | ||
1511 | pwr5g->bw40_diff[path][i] = 0; | ||
1512 | if (hwinfo[eadr] == 0xFF) { | ||
1513 | pwr5g->bw20_diff[path][i] = 0; | ||
1514 | } else { | ||
1515 | pwr5g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1516 | /*bit sign number to 8 bit sign number*/ | ||
1517 | if (pwr5g->bw20_diff[path][i] & BIT(3)) | ||
1518 | pwr5g->bw20_diff[path][i] |= 0xF0; | ||
1519 | } | ||
1520 | |||
1521 | if (hwinfo[eadr] == 0xFF) { | ||
1522 | pwr5g->ofdm_diff[path][i] = 0x04; | ||
1523 | } else { | ||
1524 | pwr5g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f); | ||
1525 | /*bit sign number to 8 bit sign number*/ | ||
1526 | if (pwr5g->ofdm_diff[path][i] & BIT(3)) | ||
1527 | pwr5g->ofdm_diff[path][i] |= 0xF0; | ||
1528 | } | ||
1529 | } | ||
1530 | |||
1531 | static void set_diff1_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path, | ||
1532 | u32 i, u32 eadr) | ||
1533 | { | ||
1534 | if (hwinfo[eadr] == 0xFF) { | ||
1535 | pwr2g->bw40_diff[path][i] = 0xFE; | ||
1536 | } else { | ||
1537 | pwr2g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1538 | if (pwr2g->bw40_diff[path][i] & BIT(3)) | ||
1539 | pwr2g->bw40_diff[path][i] |= 0xF0; | ||
1540 | } | ||
1541 | |||
1542 | if (hwinfo[eadr] == 0xFF) { | ||
1543 | pwr2g->bw20_diff[path][i] = 0xFE; | ||
1544 | } else { | ||
1545 | pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0x0f); | ||
1546 | if (pwr2g->bw20_diff[path][i] & BIT(3)) | ||
1547 | pwr2g->bw20_diff[path][i] |= 0xF0; | ||
1548 | } | ||
1549 | } | ||
1550 | |||
1551 | static void set_diff1_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path, | ||
1552 | u32 i, u32 eadr) | ||
1553 | { | ||
1554 | if (hwinfo[eadr] == 0xFF) { | ||
1555 | pwr5g->bw40_diff[path][i] = 0xFE; | ||
1556 | } else { | ||
1557 | pwr5g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1558 | if (pwr5g->bw40_diff[path][i] & BIT(3)) | ||
1559 | pwr5g->bw40_diff[path][i] |= 0xF0; | ||
1560 | } | ||
1561 | |||
1562 | if (hwinfo[eadr] == 0xFF) { | ||
1563 | pwr5g->bw20_diff[path][i] = 0xFE; | ||
1564 | } else { | ||
1565 | pwr5g->bw20_diff[path][i] = (hwinfo[eadr] & 0x0f); | ||
1566 | if (pwr5g->bw20_diff[path][i] & BIT(3)) | ||
1567 | pwr5g->bw20_diff[path][i] |= 0xF0; | ||
1568 | } | ||
1569 | } | ||
1570 | |||
1571 | static void set_diff2_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path, | ||
1572 | u32 i, u32 eadr) | ||
1573 | { | ||
1574 | if (hwinfo[eadr] == 0xFF) { | ||
1575 | pwr2g->ofdm_diff[path][i] = 0xFE; | ||
1576 | } else { | ||
1577 | pwr2g->ofdm_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1578 | if (pwr2g->ofdm_diff[path][i] & BIT(3)) | ||
1579 | pwr2g->ofdm_diff[path][i] |= 0xF0; | ||
1580 | } | ||
1581 | |||
1582 | if (hwinfo[eadr] == 0xFF) { | ||
1583 | pwr2g->cck_diff[path][i] = 0xFE; | ||
1584 | } else { | ||
1585 | pwr2g->cck_diff[path][i] = (hwinfo[eadr]&0x0f); | ||
1586 | if (pwr2g->cck_diff[path][i] & BIT(3)) | ||
1587 | pwr2g->cck_diff[path][i] |= 0xF0; | ||
1588 | } | ||
1589 | } | ||
1590 | |||
1591 | static void _rtl8188e_read_power_value_fromprom(struct ieee80211_hw *hw, | ||
1592 | struct txpower_info_2g *pwr2g, | ||
1593 | struct txpower_info_5g *pwr5g, | ||
1594 | bool autoload_fail, | ||
1595 | u8 *hwinfo) | ||
1596 | { | ||
1597 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1598 | u32 path, eadr = EEPROM_TX_PWR_INX, i; | ||
1599 | |||
1600 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1601 | "hal_ReadPowerValueFromPROM88E(): PROMContent[0x%x]= 0x%x\n", | ||
1602 | (eadr+1), hwinfo[eadr+1]); | ||
1603 | if (0xFF == hwinfo[eadr+1]) | ||
1604 | autoload_fail = true; | ||
1605 | |||
1606 | if (autoload_fail) { | ||
1607 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1608 | "auto load fail : Use Default value!\n"); | ||
1609 | for (path = 0; path < MAX_RF_PATH; path++) { | ||
1610 | /* 2.4G default value */ | ||
1611 | for (i = 0; i < MAX_CHNL_GROUP_24G; i++) { | ||
1612 | pwr2g->index_cck_base[path][i] = 0x2D; | ||
1613 | pwr2g->index_bw40_base[path][i] = 0x2D; | ||
1614 | } | ||
1615 | for (i = 0; i < MAX_TX_COUNT; i++) { | ||
1616 | if (i == 0) { | ||
1617 | pwr2g->bw20_diff[path][0] = 0x02; | ||
1618 | pwr2g->ofdm_diff[path][0] = 0x04; | ||
1619 | } else { | ||
1620 | pwr2g->bw20_diff[path][i] = 0xFE; | ||
1621 | pwr2g->bw40_diff[path][i] = 0xFE; | ||
1622 | pwr2g->cck_diff[path][i] = 0xFE; | ||
1623 | pwr2g->ofdm_diff[path][i] = 0xFE; | ||
1624 | } | ||
1625 | } | ||
1626 | } | ||
1627 | return; | ||
1628 | } | ||
1629 | |||
1630 | for (path = 0; path < MAX_RF_PATH; path++) { | ||
1631 | /*2.4G default value*/ | ||
1632 | for (i = 0; i < MAX_CHNL_GROUP_24G; i++) { | ||
1633 | pwr2g->index_cck_base[path][i] = hwinfo[eadr++]; | ||
1634 | if (pwr2g->index_cck_base[path][i] == 0xFF) | ||
1635 | pwr2g->index_cck_base[path][i] = 0x2D; | ||
1636 | } | ||
1637 | for (i = 0; i < MAX_CHNL_GROUP_24G-1; i++) { | ||
1638 | pwr2g->index_bw40_base[path][i] = hwinfo[eadr++]; | ||
1639 | if (pwr2g->index_bw40_base[path][i] == 0xFF) | ||
1640 | pwr2g->index_bw40_base[path][i] = 0x2D; | ||
1641 | } | ||
1642 | for (i = 0; i < MAX_TX_COUNT; i++) { | ||
1643 | if (i == 0) { | ||
1644 | set_diff0_2g(pwr2g, hwinfo, path, i, eadr); | ||
1645 | eadr++; | ||
1646 | } else { | ||
1647 | set_diff1_2g(pwr2g, hwinfo, path, i, eadr); | ||
1648 | eadr++; | ||
1649 | |||
1650 | set_diff2_2g(pwr2g, hwinfo, path, i, eadr); | ||
1651 | eadr++; | ||
1652 | } | ||
1653 | } | ||
1654 | |||
1655 | /*5G default value*/ | ||
1656 | for (i = 0; i < MAX_CHNL_GROUP_5G; i++) { | ||
1657 | pwr5g->index_bw40_base[path][i] = hwinfo[eadr++]; | ||
1658 | if (pwr5g->index_bw40_base[path][i] == 0xFF) | ||
1659 | pwr5g->index_bw40_base[path][i] = 0xFE; | ||
1660 | } | ||
1661 | |||
1662 | for (i = 0; i < MAX_TX_COUNT; i++) { | ||
1663 | if (i == 0) { | ||
1664 | set_diff0_5g(pwr5g, hwinfo, path, i, eadr); | ||
1665 | eadr++; | ||
1666 | } else { | ||
1667 | set_diff1_5g(pwr5g, hwinfo, path, i, eadr); | ||
1668 | eadr++; | ||
1669 | } | ||
1670 | } | ||
1671 | |||
1672 | if (hwinfo[eadr] == 0xFF) { | ||
1673 | pwr5g->ofdm_diff[path][1] = 0xFE; | ||
1674 | pwr5g->ofdm_diff[path][2] = 0xFE; | ||
1675 | } else { | ||
1676 | pwr5g->ofdm_diff[path][1] = (hwinfo[eadr] & 0xf0) >> 4; | ||
1677 | pwr5g->ofdm_diff[path][2] = (hwinfo[eadr] & 0x0f); | ||
1678 | } | ||
1679 | eadr++; | ||
1680 | |||
1681 | if (hwinfo[eadr] == 0xFF) | ||
1682 | pwr5g->ofdm_diff[path][3] = 0xFE; | ||
1683 | else | ||
1684 | pwr5g->ofdm_diff[path][3] = (hwinfo[eadr]&0x0f); | ||
1685 | eadr++; | ||
1686 | |||
1687 | for (i = 1; i < MAX_TX_COUNT; i++) { | ||
1688 | if (pwr5g->ofdm_diff[path][i] == 0xFF) | ||
1689 | pwr5g->ofdm_diff[path][i] = 0xFE; | ||
1690 | else if (pwr5g->ofdm_diff[path][i] & BIT(3)) | ||
1691 | pwr5g->ofdm_diff[path][i] |= 0xF0; | ||
1692 | } | ||
1693 | } | ||
1694 | } | ||
1695 | |||
1696 | static void _rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | ||
1697 | bool autoload_fail, | ||
1698 | u8 *hwinfo) | ||
1699 | { | ||
1700 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1701 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1702 | struct txpower_info_2g pwrinfo24g; | ||
1703 | struct txpower_info_5g pwrinfo5g; | ||
1704 | u8 rf_path, index; | ||
1705 | u8 i; | ||
1706 | int jj = EEPROM_RF_BOARD_OPTION_88E; | ||
1707 | int kk = EEPROM_THERMAL_METER_88E; | ||
1708 | |||
1709 | _rtl8188e_read_power_value_fromprom(hw, &pwrinfo24g, &pwrinfo5g, | ||
1710 | autoload_fail, hwinfo); | ||
1711 | |||
1712 | for (rf_path = 0; rf_path < 2; rf_path++) { | ||
1713 | for (i = 0; i < 14; i++) { | ||
1714 | index = get_chnl_group(i+1); | ||
1715 | |||
1716 | rtlefuse->txpwrlevel_cck[rf_path][i] = | ||
1717 | pwrinfo24g.index_cck_base[rf_path][index]; | ||
1718 | if (i == 13) | ||
1719 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = | ||
1720 | pwrinfo24g.index_bw40_base[rf_path][4]; | ||
1721 | else | ||
1722 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = | ||
1723 | pwrinfo24g.index_bw40_base[rf_path][index]; | ||
1724 | rtlefuse->txpwr_ht20diff[rf_path][i] = | ||
1725 | pwrinfo24g.bw20_diff[rf_path][0]; | ||
1726 | rtlefuse->txpwr_legacyhtdiff[rf_path][i] = | ||
1727 | pwrinfo24g.ofdm_diff[rf_path][0]; | ||
1728 | } | ||
1729 | |||
1730 | for (i = 0; i < 14; i++) { | ||
1731 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, | ||
1732 | "RF(%d)-Ch(%d) [CCK / HT40_1S ] = " | ||
1733 | "[0x%x / 0x%x ]\n", rf_path, i, | ||
1734 | rtlefuse->txpwrlevel_cck[rf_path][i], | ||
1735 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i]); | ||
1736 | } | ||
1737 | } | ||
1738 | |||
1739 | if (!autoload_fail) | ||
1740 | rtlefuse->eeprom_thermalmeter = hwinfo[kk]; | ||
1741 | else | ||
1742 | rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; | ||
1743 | |||
1744 | if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) { | ||
1745 | rtlefuse->apk_thermalmeterignore = true; | ||
1746 | rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; | ||
1747 | } | ||
1748 | |||
1749 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; | ||
1750 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, | ||
1751 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | ||
1752 | |||
1753 | if (!autoload_fail) { | ||
1754 | rtlefuse->eeprom_regulatory = hwinfo[jj] & 0x07;/*bit0~2*/ | ||
1755 | if (hwinfo[jj] == 0xFF) | ||
1756 | rtlefuse->eeprom_regulatory = 0; | ||
1757 | } else { | ||
1758 | rtlefuse->eeprom_regulatory = 0; | ||
1759 | } | ||
1760 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, | ||
1761 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | ||
1762 | } | ||
1763 | |||
1764 | static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw) | ||
1765 | { | ||
1766 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1767 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1768 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1769 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
1770 | u16 i, usvalue; | ||
1771 | u8 hwinfo[HWSET_MAX_SIZE]; | ||
1772 | u16 eeprom_id; | ||
1773 | int jj = EEPROM_RF_BOARD_OPTION_88E; | ||
1774 | int kk = EEPROM_RF_FEATURE_OPTION_88E; | ||
1775 | |||
1776 | if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { | ||
1777 | rtl_efuse_shadow_map_update(hw); | ||
1778 | |||
1779 | memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], | ||
1780 | HWSET_MAX_SIZE); | ||
1781 | } else if (rtlefuse->epromtype == EEPROM_93C46) { | ||
1782 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1783 | "RTL819X Not boot from eeprom, check it !!"); | ||
1784 | } | ||
1785 | |||
1786 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), | ||
1787 | hwinfo, HWSET_MAX_SIZE); | ||
1788 | |||
1789 | eeprom_id = *((u16 *)&hwinfo[0]); | ||
1790 | if (eeprom_id != RTL8188E_EEPROM_ID) { | ||
1791 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1792 | "EEPROM ID(%#x) is invalid!!\n", eeprom_id); | ||
1793 | rtlefuse->autoload_failflag = true; | ||
1794 | } else { | ||
1795 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); | ||
1796 | rtlefuse->autoload_failflag = false; | ||
1797 | } | ||
1798 | |||
1799 | if (rtlefuse->autoload_failflag == true) | ||
1800 | return; | ||
1801 | /*VID DID SVID SDID*/ | ||
1802 | rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; | ||
1803 | rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; | ||
1804 | rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; | ||
1805 | rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; | ||
1806 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1807 | "EEPROMId = 0x%4x\n", eeprom_id); | ||
1808 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1809 | "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); | ||
1810 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1811 | "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); | ||
1812 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1813 | "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); | ||
1814 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1815 | "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); | ||
1816 | /*customer ID*/ | ||
1817 | rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; | ||
1818 | if (rtlefuse->eeprom_oemid == 0xFF) | ||
1819 | rtlefuse->eeprom_oemid = 0; | ||
1820 | |||
1821 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1822 | "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); | ||
1823 | /*EEPROM version*/ | ||
1824 | rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; | ||
1825 | /*mac address*/ | ||
1826 | for (i = 0; i < 6; i += 2) { | ||
1827 | usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; | ||
1828 | *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; | ||
1829 | } | ||
1830 | |||
1831 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
1832 | "dev_addr: %pM\n", rtlefuse->dev_addr); | ||
1833 | /*channel plan */ | ||
1834 | rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; | ||
1835 | /* set channel paln to world wide 13 */ | ||
1836 | rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; | ||
1837 | /*tx power*/ | ||
1838 | _rtl88ee_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, | ||
1839 | hwinfo); | ||
1840 | rtlefuse->txpwr_fromeprom = true; | ||
1841 | |||
1842 | rtl8188ee_read_bt_coexist_info_from_hwpg(hw, | ||
1843 | rtlefuse->autoload_failflag, | ||
1844 | hwinfo); | ||
1845 | /*board type*/ | ||
1846 | rtlefuse->board_type = (((*(u8 *)&hwinfo[jj]) & 0xE0) >> 5); | ||
1847 | /*Wake on wlan*/ | ||
1848 | rtlefuse->wowlan_enable = ((hwinfo[kk] & 0x40) >> 6); | ||
1849 | /*parse xtal*/ | ||
1850 | rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_88E]; | ||
1851 | if (hwinfo[EEPROM_XTAL_88E]) | ||
1852 | rtlefuse->crystalcap = 0x20; | ||
1853 | /*antenna diversity*/ | ||
1854 | rtlefuse->antenna_div_cfg = (hwinfo[jj] & 0x18) >> 3; | ||
1855 | if (hwinfo[jj] == 0xFF) | ||
1856 | rtlefuse->antenna_div_cfg = 0; | ||
1857 | if (rppriv->bt_coexist.eeprom_bt_coexist != 0 && | ||
1858 | rppriv->bt_coexist.eeprom_bt_ant_num == ANT_X1) | ||
1859 | rtlefuse->antenna_div_cfg = 0; | ||
1860 | |||
1861 | rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E]; | ||
1862 | if (rtlefuse->antenna_div_type == 0xFF) | ||
1863 | rtlefuse->antenna_div_type = 0x01; | ||
1864 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV || | ||
1865 | rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1866 | rtlefuse->antenna_div_cfg = 1; | ||
1867 | |||
1868 | if (rtlhal->oem_id == RT_CID_DEFAULT) { | ||
1869 | switch (rtlefuse->eeprom_oemid) { | ||
1870 | case EEPROM_CID_DEFAULT: | ||
1871 | if (rtlefuse->eeprom_did == 0x8179) { | ||
1872 | if (rtlefuse->eeprom_svid == 0x1025) { | ||
1873 | rtlhal->oem_id = RT_CID_819x_Acer; | ||
1874 | } else if ((rtlefuse->eeprom_svid == 0x10EC && | ||
1875 | rtlefuse->eeprom_smid == 0x0179) || | ||
1876 | (rtlefuse->eeprom_svid == 0x17AA && | ||
1877 | rtlefuse->eeprom_smid == 0x0179)) { | ||
1878 | rtlhal->oem_id = RT_CID_819x_Lenovo; | ||
1879 | } else if (rtlefuse->eeprom_svid == 0x103c && | ||
1880 | rtlefuse->eeprom_smid == 0x197d) { | ||
1881 | rtlhal->oem_id = RT_CID_819x_HP; | ||
1882 | } else { | ||
1883 | rtlhal->oem_id = RT_CID_DEFAULT; | ||
1884 | } | ||
1885 | } else { | ||
1886 | rtlhal->oem_id = RT_CID_DEFAULT; | ||
1887 | } | ||
1888 | break; | ||
1889 | case EEPROM_CID_TOSHIBA: | ||
1890 | rtlhal->oem_id = RT_CID_TOSHIBA; | ||
1891 | break; | ||
1892 | case EEPROM_CID_QMI: | ||
1893 | rtlhal->oem_id = RT_CID_819x_QMI; | ||
1894 | break; | ||
1895 | case EEPROM_CID_WHQL: | ||
1896 | default: | ||
1897 | rtlhal->oem_id = RT_CID_DEFAULT; | ||
1898 | break; | ||
1899 | } | ||
1900 | } | ||
1901 | } | ||
1902 | |||
1903 | static void _rtl88ee_hal_customized_behavior(struct ieee80211_hw *hw) | ||
1904 | { | ||
1905 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1906 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
1907 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1908 | |||
1909 | pcipriv->ledctl.led_opendrain = true; | ||
1910 | |||
1911 | switch (rtlhal->oem_id) { | ||
1912 | case RT_CID_819x_HP: | ||
1913 | pcipriv->ledctl.led_opendrain = true; | ||
1914 | break; | ||
1915 | case RT_CID_819x_Lenovo: | ||
1916 | case RT_CID_DEFAULT: | ||
1917 | case RT_CID_TOSHIBA: | ||
1918 | case RT_CID_CCX: | ||
1919 | case RT_CID_819x_Acer: | ||
1920 | case RT_CID_WHQL: | ||
1921 | default: | ||
1922 | break; | ||
1923 | } | ||
1924 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
1925 | "RT Customized ID: 0x%02X\n", rtlhal->oem_id); | ||
1926 | } | ||
1927 | |||
1928 | void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw) | ||
1929 | { | ||
1930 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1931 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1932 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1933 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1934 | u8 tmp_u1b; | ||
1935 | |||
1936 | rtlhal->version = _rtl88ee_read_chip_version(hw); | ||
1937 | if (get_rf_type(rtlphy) == RF_1T1R) { | ||
1938 | rtlpriv->dm.rfpath_rxenable[0] = true; | ||
1939 | } else { | ||
1940 | rtlpriv->dm.rfpath_rxenable[0] = true; | ||
1941 | rtlpriv->dm.rfpath_rxenable[1] = true; | ||
1942 | } | ||
1943 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", | ||
1944 | rtlhal->version); | ||
1945 | tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); | ||
1946 | if (tmp_u1b & BIT(4)) { | ||
1947 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); | ||
1948 | rtlefuse->epromtype = EEPROM_93C46; | ||
1949 | } else { | ||
1950 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); | ||
1951 | rtlefuse->epromtype = EEPROM_BOOT_EFUSE; | ||
1952 | } | ||
1953 | if (tmp_u1b & BIT(5)) { | ||
1954 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); | ||
1955 | rtlefuse->autoload_failflag = false; | ||
1956 | _rtl88ee_read_adapter_info(hw); | ||
1957 | } else { | ||
1958 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); | ||
1959 | } | ||
1960 | _rtl88ee_hal_customized_behavior(hw); | ||
1961 | } | ||
1962 | |||
1963 | static void rtl88ee_update_hal_rate_table(struct ieee80211_hw *hw, | ||
1964 | struct ieee80211_sta *sta) | ||
1965 | { | ||
1966 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1967 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
1968 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1969 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1970 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1971 | u32 ratr_value; | ||
1972 | u8 ratr_index = 0; | ||
1973 | u8 nmode = mac->ht_enable; | ||
1974 | u8 mimo_ps = IEEE80211_SMPS_OFF; | ||
1975 | u16 shortgi_rate; | ||
1976 | u32 tmp_ratr_value; | ||
1977 | u8 ctx40 = mac->bw_40; | ||
1978 | u16 cap = sta->ht_cap.cap; | ||
1979 | u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; | ||
1980 | u8 short20 = (cap & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; | ||
1981 | enum wireless_mode wirelessmode = mac->mode; | ||
1982 | |||
1983 | if (rtlhal->current_bandtype == BAND_ON_5G) | ||
1984 | ratr_value = sta->supp_rates[1] << 4; | ||
1985 | else | ||
1986 | ratr_value = sta->supp_rates[0]; | ||
1987 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
1988 | ratr_value = 0xfff; | ||
1989 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | ||
1990 | sta->ht_cap.mcs.rx_mask[0] << 12); | ||
1991 | switch (wirelessmode) { | ||
1992 | case WIRELESS_MODE_B: | ||
1993 | if (ratr_value & 0x0000000c) | ||
1994 | ratr_value &= 0x0000000d; | ||
1995 | else | ||
1996 | ratr_value &= 0x0000000f; | ||
1997 | break; | ||
1998 | case WIRELESS_MODE_G: | ||
1999 | ratr_value &= 0x00000FF5; | ||
2000 | break; | ||
2001 | case WIRELESS_MODE_N_24G: | ||
2002 | case WIRELESS_MODE_N_5G: | ||
2003 | nmode = 1; | ||
2004 | if (mimo_ps == IEEE80211_SMPS_STATIC) { | ||
2005 | ratr_value &= 0x0007F005; | ||
2006 | } else { | ||
2007 | u32 ratr_mask; | ||
2008 | |||
2009 | if (get_rf_type(rtlphy) == RF_1T2R || | ||
2010 | get_rf_type(rtlphy) == RF_1T1R) | ||
2011 | ratr_mask = 0x000ff005; | ||
2012 | else | ||
2013 | ratr_mask = 0x0f0ff005; | ||
2014 | |||
2015 | ratr_value &= ratr_mask; | ||
2016 | } | ||
2017 | break; | ||
2018 | default: | ||
2019 | if (rtlphy->rf_type == RF_1T2R) | ||
2020 | ratr_value &= 0x000ff0ff; | ||
2021 | else | ||
2022 | ratr_value &= 0x0f0ff0ff; | ||
2023 | |||
2024 | break; | ||
2025 | } | ||
2026 | |||
2027 | if ((rppriv->bt_coexist.bt_coexistence) && | ||
2028 | (rppriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) && | ||
2029 | (rppriv->bt_coexist.bt_cur_state) && | ||
2030 | (rppriv->bt_coexist.bt_ant_isolation) && | ||
2031 | ((rppriv->bt_coexist.bt_service == BT_SCO) || | ||
2032 | (rppriv->bt_coexist.bt_service == BT_BUSY))) | ||
2033 | ratr_value &= 0x0fffcfc0; | ||
2034 | else | ||
2035 | ratr_value &= 0x0FFFFFFF; | ||
2036 | |||
2037 | if (nmode && ((ctx40 && short40) || | ||
2038 | (!ctx40 && short20))) { | ||
2039 | ratr_value |= 0x10000000; | ||
2040 | tmp_ratr_value = (ratr_value >> 12); | ||
2041 | |||
2042 | for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { | ||
2043 | if ((1 << shortgi_rate) & tmp_ratr_value) | ||
2044 | break; | ||
2045 | } | ||
2046 | |||
2047 | shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | | ||
2048 | (shortgi_rate << 4) | (shortgi_rate); | ||
2049 | } | ||
2050 | |||
2051 | rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); | ||
2052 | |||
2053 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2054 | "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); | ||
2055 | } | ||
2056 | |||
2057 | static void rtl88ee_update_hal_rate_mask(struct ieee80211_hw *hw, | ||
2058 | struct ieee80211_sta *sta, u8 rssi) | ||
2059 | { | ||
2060 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2061 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
2062 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2063 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
2064 | struct rtl_sta_info *sta_entry = NULL; | ||
2065 | u32 ratr_bitmap; | ||
2066 | u8 ratr_index; | ||
2067 | u16 cap = sta->ht_cap.cap; | ||
2068 | u8 ctx40 = (cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; | ||
2069 | u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; | ||
2070 | u8 short20 = (cap & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; | ||
2071 | enum wireless_mode wirelessmode = 0; | ||
2072 | bool shortgi = false; | ||
2073 | u8 rate_mask[5]; | ||
2074 | u8 macid = 0; | ||
2075 | u8 mimo_ps = IEEE80211_SMPS_OFF; | ||
2076 | |||
2077 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
2078 | wirelessmode = sta_entry->wireless_mode; | ||
2079 | if (mac->opmode == NL80211_IFTYPE_STATION || | ||
2080 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
2081 | ctx40 = mac->bw_40; | ||
2082 | else if (mac->opmode == NL80211_IFTYPE_AP || | ||
2083 | mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2084 | macid = sta->aid + 1; | ||
2085 | |||
2086 | if (rtlhal->current_bandtype == BAND_ON_5G) | ||
2087 | ratr_bitmap = sta->supp_rates[1] << 4; | ||
2088 | else | ||
2089 | ratr_bitmap = sta->supp_rates[0]; | ||
2090 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2091 | ratr_bitmap = 0xfff; | ||
2092 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | ||
2093 | sta->ht_cap.mcs.rx_mask[0] << 12); | ||
2094 | switch (wirelessmode) { | ||
2095 | case WIRELESS_MODE_B: | ||
2096 | ratr_index = RATR_INX_WIRELESS_B; | ||
2097 | if (ratr_bitmap & 0x0000000c) | ||
2098 | ratr_bitmap &= 0x0000000d; | ||
2099 | else | ||
2100 | ratr_bitmap &= 0x0000000f; | ||
2101 | break; | ||
2102 | case WIRELESS_MODE_G: | ||
2103 | ratr_index = RATR_INX_WIRELESS_GB; | ||
2104 | |||
2105 | if (rssi == 1) | ||
2106 | ratr_bitmap &= 0x00000f00; | ||
2107 | else if (rssi == 2) | ||
2108 | ratr_bitmap &= 0x00000ff0; | ||
2109 | else | ||
2110 | ratr_bitmap &= 0x00000ff5; | ||
2111 | break; | ||
2112 | case WIRELESS_MODE_A: | ||
2113 | ratr_index = RATR_INX_WIRELESS_A; | ||
2114 | ratr_bitmap &= 0x00000ff0; | ||
2115 | break; | ||
2116 | case WIRELESS_MODE_N_24G: | ||
2117 | case WIRELESS_MODE_N_5G: | ||
2118 | ratr_index = RATR_INX_WIRELESS_NGB; | ||
2119 | |||
2120 | if (mimo_ps == IEEE80211_SMPS_STATIC) { | ||
2121 | if (rssi == 1) | ||
2122 | ratr_bitmap &= 0x00070000; | ||
2123 | else if (rssi == 2) | ||
2124 | ratr_bitmap &= 0x0007f000; | ||
2125 | else | ||
2126 | ratr_bitmap &= 0x0007f005; | ||
2127 | } else { | ||
2128 | if (rtlphy->rf_type == RF_1T2R || | ||
2129 | rtlphy->rf_type == RF_1T1R) { | ||
2130 | if (ctx40) { | ||
2131 | if (rssi == 1) | ||
2132 | ratr_bitmap &= 0x000f0000; | ||
2133 | else if (rssi == 2) | ||
2134 | ratr_bitmap &= 0x000ff000; | ||
2135 | else | ||
2136 | ratr_bitmap &= 0x000ff015; | ||
2137 | } else { | ||
2138 | if (rssi == 1) | ||
2139 | ratr_bitmap &= 0x000f0000; | ||
2140 | else if (rssi == 2) | ||
2141 | ratr_bitmap &= 0x000ff000; | ||
2142 | else | ||
2143 | ratr_bitmap &= 0x000ff005; | ||
2144 | } | ||
2145 | } else { | ||
2146 | if (ctx40) { | ||
2147 | if (rssi == 1) | ||
2148 | ratr_bitmap &= 0x0f8f0000; | ||
2149 | else if (rssi == 2) | ||
2150 | ratr_bitmap &= 0x0f8ff000; | ||
2151 | else | ||
2152 | ratr_bitmap &= 0x0f8ff015; | ||
2153 | } else { | ||
2154 | if (rssi == 1) | ||
2155 | ratr_bitmap &= 0x0f8f0000; | ||
2156 | else if (rssi == 2) | ||
2157 | ratr_bitmap &= 0x0f8ff000; | ||
2158 | else | ||
2159 | ratr_bitmap &= 0x0f8ff005; | ||
2160 | } | ||
2161 | } | ||
2162 | } | ||
2163 | |||
2164 | if ((ctx40 && short40) || (!ctx40 && short20)) { | ||
2165 | if (macid == 0) | ||
2166 | shortgi = true; | ||
2167 | else if (macid == 1) | ||
2168 | shortgi = false; | ||
2169 | } | ||
2170 | break; | ||
2171 | default: | ||
2172 | ratr_index = RATR_INX_WIRELESS_NGB; | ||
2173 | |||
2174 | if (rtlphy->rf_type == RF_1T2R) | ||
2175 | ratr_bitmap &= 0x000ff0ff; | ||
2176 | else | ||
2177 | ratr_bitmap &= 0x0f0ff0ff; | ||
2178 | break; | ||
2179 | } | ||
2180 | sta_entry->ratr_index = ratr_index; | ||
2181 | |||
2182 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2183 | "ratr_bitmap :%x\n", ratr_bitmap); | ||
2184 | *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | | ||
2185 | (ratr_index << 28); | ||
2186 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; | ||
2187 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2188 | "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", | ||
2189 | ratr_index, ratr_bitmap, rate_mask[0], rate_mask[1], | ||
2190 | rate_mask[2], rate_mask[3], rate_mask[4]); | ||
2191 | rtl88e_fill_h2c_cmd(hw, H2C_88E_RA_MASK, 5, rate_mask); | ||
2192 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); | ||
2193 | } | ||
2194 | |||
2195 | void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw, | ||
2196 | struct ieee80211_sta *sta, u8 rssi) | ||
2197 | { | ||
2198 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2199 | |||
2200 | if (rtlpriv->dm.useramask) | ||
2201 | rtl88ee_update_hal_rate_mask(hw, sta, rssi); | ||
2202 | else | ||
2203 | rtl88ee_update_hal_rate_table(hw, sta); | ||
2204 | } | ||
2205 | |||
2206 | void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw) | ||
2207 | { | ||
2208 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2209 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2210 | u16 sifs_timer; | ||
2211 | |||
2212 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, | ||
2213 | (u8 *)&mac->slot_time); | ||
2214 | if (!mac->ht_enable) | ||
2215 | sifs_timer = 0x0a0a; | ||
2216 | else | ||
2217 | sifs_timer = 0x0e0e; | ||
2218 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); | ||
2219 | } | ||
2220 | |||
2221 | bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) | ||
2222 | { | ||
2223 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2224 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2225 | enum rf_pwrstate state_toset; | ||
2226 | u32 u4tmp; | ||
2227 | bool actuallyset = false; | ||
2228 | |||
2229 | if (rtlpriv->rtlhal.being_init_adapter) | ||
2230 | return false; | ||
2231 | |||
2232 | if (ppsc->swrf_processing) | ||
2233 | return false; | ||
2234 | |||
2235 | spin_lock(&rtlpriv->locks.rf_ps_lock); | ||
2236 | if (ppsc->rfchange_inprogress) { | ||
2237 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2238 | return false; | ||
2239 | } else { | ||
2240 | ppsc->rfchange_inprogress = true; | ||
2241 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2242 | } | ||
2243 | |||
2244 | u4tmp = rtl_read_dword(rtlpriv, REG_GPIO_OUTPUT); | ||
2245 | state_toset = (u4tmp & BIT(31)) ? ERFON : ERFOFF; | ||
2246 | |||
2247 | |||
2248 | if ((ppsc->hwradiooff == true) && (state_toset == ERFON)) { | ||
2249 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2250 | "GPIOChangeRF - HW Radio ON, RF ON\n"); | ||
2251 | |||
2252 | state_toset = ERFON; | ||
2253 | ppsc->hwradiooff = false; | ||
2254 | actuallyset = true; | ||
2255 | } else if ((ppsc->hwradiooff == false) && (state_toset == ERFOFF)) { | ||
2256 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2257 | "GPIOChangeRF - HW Radio OFF, RF OFF\n"); | ||
2258 | |||
2259 | state_toset = ERFOFF; | ||
2260 | ppsc->hwradiooff = true; | ||
2261 | actuallyset = true; | ||
2262 | } | ||
2263 | |||
2264 | if (actuallyset) { | ||
2265 | spin_lock(&rtlpriv->locks.rf_ps_lock); | ||
2266 | ppsc->rfchange_inprogress = false; | ||
2267 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2268 | } else { | ||
2269 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) | ||
2270 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
2271 | |||
2272 | spin_lock(&rtlpriv->locks.rf_ps_lock); | ||
2273 | ppsc->rfchange_inprogress = false; | ||
2274 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2275 | } | ||
2276 | |||
2277 | *valid = 1; | ||
2278 | return !ppsc->hwradiooff; | ||
2279 | } | ||
2280 | |||
2281 | static void add_one_key(struct ieee80211_hw *hw, u8 *macaddr, | ||
2282 | struct rtl_mac *mac, u32 key, u32 id, | ||
2283 | u8 enc_algo, bool is_pairwise) | ||
2284 | { | ||
2285 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2286 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
2287 | |||
2288 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "add one entry\n"); | ||
2289 | if (is_pairwise) { | ||
2290 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set Pairwise key\n"); | ||
2291 | |||
2292 | rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo, | ||
2293 | CAM_CONFIG_NO_USEDK, | ||
2294 | rtlpriv->sec.key_buf[key]); | ||
2295 | } else { | ||
2296 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set group key\n"); | ||
2297 | |||
2298 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
2299 | rtl_cam_add_one_entry(hw, rtlefuse->dev_addr, | ||
2300 | PAIRWISE_KEYIDX, | ||
2301 | CAM_PAIRWISE_KEY_POSITION, | ||
2302 | enc_algo, | ||
2303 | CAM_CONFIG_NO_USEDK, | ||
2304 | rtlpriv->sec.key_buf[id]); | ||
2305 | } | ||
2306 | |||
2307 | rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo, | ||
2308 | CAM_CONFIG_NO_USEDK, | ||
2309 | rtlpriv->sec.key_buf[id]); | ||
2310 | } | ||
2311 | } | ||
2312 | |||
2313 | void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key, | ||
2314 | u8 *mac_ad, bool is_group, u8 enc_algo, | ||
2315 | bool is_wepkey, bool clear_all) | ||
2316 | { | ||
2317 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2318 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2319 | u8 *macaddr = mac_ad; | ||
2320 | u32 id = 0; | ||
2321 | bool is_pairwise = false; | ||
2322 | |||
2323 | static u8 cam_const_addr[4][6] = { | ||
2324 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
2325 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, | ||
2326 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, | ||
2327 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} | ||
2328 | }; | ||
2329 | static u8 cam_const_broad[] = { | ||
2330 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
2331 | }; | ||
2332 | |||
2333 | if (clear_all) { | ||
2334 | u8 idx = 0; | ||
2335 | u8 cam_offset = 0; | ||
2336 | u8 clear_number = 5; | ||
2337 | |||
2338 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); | ||
2339 | |||
2340 | for (idx = 0; idx < clear_number; idx++) { | ||
2341 | rtl_cam_mark_invalid(hw, cam_offset + idx); | ||
2342 | rtl_cam_empty_entry(hw, cam_offset + idx); | ||
2343 | |||
2344 | if (idx < 5) { | ||
2345 | memset(rtlpriv->sec.key_buf[idx], 0, | ||
2346 | MAX_KEY_LEN); | ||
2347 | rtlpriv->sec.key_len[idx] = 0; | ||
2348 | } | ||
2349 | } | ||
2350 | |||
2351 | } else { | ||
2352 | switch (enc_algo) { | ||
2353 | case WEP40_ENCRYPTION: | ||
2354 | enc_algo = CAM_WEP40; | ||
2355 | break; | ||
2356 | case WEP104_ENCRYPTION: | ||
2357 | enc_algo = CAM_WEP104; | ||
2358 | break; | ||
2359 | case TKIP_ENCRYPTION: | ||
2360 | enc_algo = CAM_TKIP; | ||
2361 | break; | ||
2362 | case AESCCMP_ENCRYPTION: | ||
2363 | enc_algo = CAM_AES; | ||
2364 | break; | ||
2365 | default: | ||
2366 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2367 | "switch case not processed\n"); | ||
2368 | enc_algo = CAM_TKIP; | ||
2369 | break; | ||
2370 | } | ||
2371 | |||
2372 | if (is_wepkey || rtlpriv->sec.use_defaultkey) { | ||
2373 | macaddr = cam_const_addr[key]; | ||
2374 | id = key; | ||
2375 | } else { | ||
2376 | if (is_group) { | ||
2377 | macaddr = cam_const_broad; | ||
2378 | id = key; | ||
2379 | } else { | ||
2380 | if (mac->opmode == NL80211_IFTYPE_AP || | ||
2381 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
2382 | id = rtl_cam_get_free_entry(hw, mac_ad); | ||
2383 | if (id >= TOTAL_CAM_ENTRY) { | ||
2384 | RT_TRACE(rtlpriv, COMP_SEC, | ||
2385 | DBG_EMERG, | ||
2386 | "Can not find free hw security cam entry\n"); | ||
2387 | return; | ||
2388 | } | ||
2389 | } else { | ||
2390 | id = CAM_PAIRWISE_KEY_POSITION; | ||
2391 | } | ||
2392 | |||
2393 | key = PAIRWISE_KEYIDX; | ||
2394 | is_pairwise = true; | ||
2395 | } | ||
2396 | } | ||
2397 | |||
2398 | if (rtlpriv->sec.key_len[key] == 0) { | ||
2399 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
2400 | "delete one entry, id is %d\n", id); | ||
2401 | if (mac->opmode == NL80211_IFTYPE_AP || | ||
2402 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
2403 | rtl_cam_del_entry(hw, mac_ad); | ||
2404 | rtl_cam_delete_one_entry(hw, mac_ad, id); | ||
2405 | } else { | ||
2406 | add_one_key(hw, macaddr, mac, key, id, enc_algo, | ||
2407 | is_pairwise); | ||
2408 | } | ||
2409 | } | ||
2410 | } | ||
2411 | |||
2412 | static void rtl8188ee_bt_var_init(struct ieee80211_hw *hw) | ||
2413 | { | ||
2414 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
2415 | struct bt_coexist_info coexist = rppriv->bt_coexist; | ||
2416 | |||
2417 | coexist.bt_coexistence = rppriv->bt_coexist.eeprom_bt_coexist; | ||
2418 | coexist.bt_ant_num = coexist.eeprom_bt_ant_num; | ||
2419 | coexist.bt_coexist_type = coexist.eeprom_bt_type; | ||
2420 | |||
2421 | if (coexist.reg_bt_iso == 2) | ||
2422 | coexist.bt_ant_isolation = coexist.eeprom_bt_ant_isol; | ||
2423 | else | ||
2424 | coexist.bt_ant_isolation = coexist.reg_bt_iso; | ||
2425 | |||
2426 | coexist.bt_radio_shared_type = coexist.eeprom_bt_radio_shared; | ||
2427 | |||
2428 | if (coexist.bt_coexistence) { | ||
2429 | if (coexist.reg_bt_sco == 1) | ||
2430 | coexist.bt_service = BT_OTHER_ACTION; | ||
2431 | else if (coexist.reg_bt_sco == 2) | ||
2432 | coexist.bt_service = BT_SCO; | ||
2433 | else if (coexist.reg_bt_sco == 4) | ||
2434 | coexist.bt_service = BT_BUSY; | ||
2435 | else if (coexist.reg_bt_sco == 5) | ||
2436 | coexist.bt_service = BT_OTHERBUSY; | ||
2437 | else | ||
2438 | coexist.bt_service = BT_IDLE; | ||
2439 | |||
2440 | coexist.bt_edca_ul = 0; | ||
2441 | coexist.bt_edca_dl = 0; | ||
2442 | coexist.bt_rssi_state = 0xff; | ||
2443 | } | ||
2444 | } | ||
2445 | |||
2446 | void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, | ||
2447 | bool auto_load_fail, u8 *hwinfo) | ||
2448 | { | ||
2449 | rtl8188ee_bt_var_init(hw); | ||
2450 | } | ||
2451 | |||
2452 | void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw) | ||
2453 | { | ||
2454 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
2455 | |||
2456 | /* 0:Low, 1:High, 2:From Efuse. */ | ||
2457 | rppriv->bt_coexist.reg_bt_iso = 2; | ||
2458 | /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ | ||
2459 | rppriv->bt_coexist.reg_bt_sco = 3; | ||
2460 | /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ | ||
2461 | rppriv->bt_coexist.reg_bt_sco = 0; | ||
2462 | } | ||
2463 | |||
2464 | void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw) | ||
2465 | { | ||
2466 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2467 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
2468 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
2469 | struct bt_coexist_info coexist = rppriv->bt_coexist; | ||
2470 | u8 u1_tmp; | ||
2471 | |||
2472 | if (coexist.bt_coexistence && | ||
2473 | ((coexist.bt_coexist_type == BT_CSR_BC4) || | ||
2474 | coexist.bt_coexist_type == BT_CSR_BC8)) { | ||
2475 | if (coexist.bt_ant_isolation) | ||
2476 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); | ||
2477 | |||
2478 | u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & | ||
2479 | BIT_OFFSET_LEN_MASK_32(0, 1); | ||
2480 | u1_tmp = u1_tmp | ((coexist.bt_ant_isolation == 1) ? | ||
2481 | 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | | ||
2482 | ((coexist.bt_service == BT_SCO) ? | ||
2483 | 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); | ||
2484 | rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); | ||
2485 | |||
2486 | rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); | ||
2487 | rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); | ||
2488 | rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); | ||
2489 | |||
2490 | /* Config to 1T1R. */ | ||
2491 | if (rtlphy->rf_type == RF_1T1R) { | ||
2492 | u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); | ||
2493 | u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); | ||
2494 | rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); | ||
2495 | |||
2496 | u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); | ||
2497 | u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); | ||
2498 | rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); | ||
2499 | } | ||
2500 | } | ||
2501 | } | ||
2502 | |||
2503 | void rtl88ee_suspend(struct ieee80211_hw *hw) | ||
2504 | { | ||
2505 | } | ||
2506 | |||
2507 | void rtl88ee_resume(struct ieee80211_hw *hw) | ||
2508 | { | ||
2509 | } | ||
2510 | |||
2511 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
2512 | void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw, | ||
2513 | bool allow_all_da, bool write_into_reg) | ||
2514 | { | ||
2515 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2516 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2517 | |||
2518 | if (allow_all_da) /* Set BIT0 */ | ||
2519 | rtlpci->receive_config |= RCR_AAP; | ||
2520 | else /* Clear BIT0 */ | ||
2521 | rtlpci->receive_config &= ~RCR_AAP; | ||
2522 | |||
2523 | if (write_into_reg) | ||
2524 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
2525 | |||
2526 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
2527 | "receive_config = 0x%08X, write_into_reg =%d\n", | ||
2528 | rtlpci->receive_config, write_into_reg); | ||
2529 | } | ||