1 /******************************************************************************
3 * Copyright(c) 2009-2014 Realtek Corporation.
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.
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
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
36 static void _rtl92ee_enable_fw_download(struct ieee80211_hw
*hw
, bool enable
)
38 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
42 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, 0x05);
44 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
+ 2);
45 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 2, tmp
& 0xf7);
47 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
48 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
& 0xfe);
52 static void _rtl92ee_write_fw(struct ieee80211_hw
*hw
,
53 enum version_8192e version
,
56 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
57 u8
*bufferptr
= (u8
*)buffer
;
58 u32 pagenums
, remainsize
;
61 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "FW size is %d bytes,\n", size
);
63 rtl_fill_dummy(bufferptr
, &size
);
65 pagenums
= size
/ FW_8192C_PAGE_SIZE
;
66 remainsize
= size
% FW_8192C_PAGE_SIZE
;
69 pr_err("Page numbers should not greater then 8\n");
71 for (page
= 0; page
< pagenums
; page
++) {
72 offset
= page
* FW_8192C_PAGE_SIZE
;
73 rtl_fw_page_write(hw
, page
, (bufferptr
+ offset
),
79 offset
= pagenums
* FW_8192C_PAGE_SIZE
;
81 rtl_fw_page_write(hw
, page
, (bufferptr
+ offset
), remainsize
);
85 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw
*hw
)
87 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
93 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
94 } while ((counter
++ < FW_8192C_POLLING_TIMEOUT_COUNT
) &&
95 (!(value32
& FWDL_CHKSUM_RPT
)));
97 if (counter
>= FW_8192C_POLLING_TIMEOUT_COUNT
) {
98 pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
102 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
103 value32
|= MCUFWDL_RDY
;
104 value32
&= ~WINTINI_RDY
;
105 rtl_write_dword(rtlpriv
, REG_MCUFWDL
, value32
);
107 rtl92ee_firmware_selfreset(hw
);
111 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
112 if (value32
& WINTINI_RDY
)
115 udelay(FW_8192C_POLLING_DELAY
*10);
117 } while (counter
++ < FW_8192C_POLLING_TIMEOUT_COUNT
);
119 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
126 int rtl92ee_download_fw(struct ieee80211_hw
*hw
, bool buse_wake_on_wlan_fw
)
128 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
129 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
130 struct rtlwifi_firmware_header
*pfwheader
;
134 enum version_8192e version
= rtlhal
->version
;
136 if (!rtlhal
->pfirmware
)
139 pfwheader
= (struct rtlwifi_firmware_header
*)rtlhal
->pfirmware
;
140 rtlhal
->fw_version
= le16_to_cpu(pfwheader
->version
);
141 rtlhal
->fw_subversion
= pfwheader
->subversion
;
142 pfwdata
= (u8
*)rtlhal
->pfirmware
;
143 fwsize
= rtlhal
->fwsize
;
144 RT_TRACE(rtlpriv
, COMP_FW
, DBG_DMESG
,
145 "normal Firmware SIZE %d\n" , fwsize
);
147 if (IS_FW_HEADER_EXIST(pfwheader
)) {
148 RT_TRACE(rtlpriv
, COMP_FW
, DBG_DMESG
,
149 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
150 pfwheader
->version
, pfwheader
->signature
,
151 (int)sizeof(struct rtlwifi_firmware_header
));
153 pfwdata
= pfwdata
+ sizeof(struct rtlwifi_firmware_header
);
154 fwsize
= fwsize
- sizeof(struct rtlwifi_firmware_header
);
156 RT_TRACE(rtlpriv
, COMP_FW
, DBG_DMESG
,
157 "Firmware no Header, Signature(%#x)\n",
158 pfwheader
->signature
);
161 if (rtlhal
->mac_func_enable
) {
162 if (rtl_read_byte(rtlpriv
, REG_MCUFWDL
) & BIT(7)) {
163 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, 0);
164 rtl92ee_firmware_selfreset(hw
);
167 _rtl92ee_enable_fw_download(hw
, true);
168 _rtl92ee_write_fw(hw
, version
, pfwdata
, fwsize
);
169 _rtl92ee_enable_fw_download(hw
, false);
171 err
= _rtl92ee_fw_free_to_go(hw
);
176 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw
*hw
, u8 boxnum
)
178 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
182 val_hmetfr
= rtl_read_byte(rtlpriv
, REG_HMETFR
);
183 if (((val_hmetfr
>> boxnum
) & BIT(0)) == 0)
188 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw
*hw
, u8 element_id
,
189 u32 cmd_len
, u8
*cmdbuffer
)
191 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
192 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
193 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
195 u16 box_reg
= 0, box_extreg
= 0;
197 bool isfw_read
= false;
199 bool bwrite_sucess
= false;
200 u8 wait_h2c_limmit
= 100;
201 u8 boxcontent
[4], boxextcontent
[4];
202 u32 h2c_waitcounter
= 0;
206 if (ppsc
->dot11_psmode
!= EACTIVE
||
207 ppsc
->inactive_pwrstate
== ERFOFF
) {
208 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
209 "FillH2CCommand8192E(): Return because RF is off!!!\n");
213 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
, "come in\n");
215 /* 1. Prevent race condition in setting H2C cmd.
216 * (copy from MgntActSet_RF_State().)
219 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
, flag
);
220 if (rtlhal
->h2c_setinprogress
) {
221 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
222 "H2C set in progress! Wait to set..element_id(%d).\n",
225 while (rtlhal
->h2c_setinprogress
) {
226 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
,
229 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
230 "Wait 100 us (%d times)...\n",
234 if (h2c_waitcounter
> 1000)
236 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
,
239 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
241 rtlhal
->h2c_setinprogress
= true;
242 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
247 while (!bwrite_sucess
) {
248 /* 2. Find the last BOX number which has been writen. */
249 boxnum
= rtlhal
->last_hmeboxnum
;
252 box_reg
= REG_HMEBOX_0
;
253 box_extreg
= REG_HMEBOX_EXT_0
;
256 box_reg
= REG_HMEBOX_1
;
257 box_extreg
= REG_HMEBOX_EXT_1
;
260 box_reg
= REG_HMEBOX_2
;
261 box_extreg
= REG_HMEBOX_EXT_2
;
264 box_reg
= REG_HMEBOX_3
;
265 box_extreg
= REG_HMEBOX_EXT_3
;
268 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_LOUD
,
269 "switch case %#x not processed\n", boxnum
);
273 /* 3. Check if the box content is empty. */
275 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_CR
);
277 if (u1b_tmp
!= 0xea) {
280 if (rtl_read_byte(rtlpriv
, REG_TXDMA_STATUS
) == 0xea ||
281 rtl_read_byte(rtlpriv
, REG_TXPKT_EMPTY
) == 0xea)
282 rtl_write_byte(rtlpriv
, REG_SYS_CFG1
+ 3, 0xff);
286 wait_h2c_limmit
= 100;
287 isfw_read
= _rtl92ee_check_fw_read_last_h2c(hw
, boxnum
);
290 if (wait_h2c_limmit
== 0) {
291 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
292 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
298 _rtl92ee_check_fw_read_last_h2c(hw
, boxnum
);
299 u1b_tmp
= rtl_read_byte(rtlpriv
, 0x130);
300 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
301 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
306 /* If Fw has not read the last
307 * H2C cmd, break and give up this H2C.
310 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
311 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
315 /* 4. Fill the H2C cmd into box */
316 memset(boxcontent
, 0, sizeof(boxcontent
));
317 memset(boxextcontent
, 0, sizeof(boxextcontent
));
318 boxcontent
[0] = element_id
;
319 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
320 "Write element_id box_reg(%4x) = %2x\n",
321 box_reg
, element_id
);
327 /*boxcontent[0] &= ~(BIT(7));*/
328 memcpy((u8
*)(boxcontent
) + 1,
329 cmdbuffer
+ buf_index
, cmd_len
);
331 for (idx
= 0; idx
< 4; idx
++) {
332 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
340 /*boxcontent[0] |= (BIT(7));*/
341 memcpy((u8
*)(boxextcontent
),
342 cmdbuffer
+ buf_index
+3, cmd_len
-3);
343 memcpy((u8
*)(boxcontent
) + 1,
344 cmdbuffer
+ buf_index
, 3);
346 for (idx
= 0; idx
< 4; idx
++) {
347 rtl_write_byte(rtlpriv
, box_extreg
+ idx
,
351 for (idx
= 0; idx
< 4; idx
++) {
352 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
357 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_LOUD
,
358 "switch case %#x not processed\n", cmd_len
);
362 bwrite_sucess
= true;
364 rtlhal
->last_hmeboxnum
= boxnum
+ 1;
365 if (rtlhal
->last_hmeboxnum
== 4)
366 rtlhal
->last_hmeboxnum
= 0;
368 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
369 "pHalData->last_hmeboxnum = %d\n",
370 rtlhal
->last_hmeboxnum
);
373 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
, flag
);
374 rtlhal
->h2c_setinprogress
= false;
375 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
377 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
, "go out\n");
380 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw
*hw
,
381 u8 element_id
, u32 cmd_len
, u8
*cmdbuffer
)
383 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
386 if (!rtlhal
->fw_ready
) {
388 "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
392 memset(tmp_cmdbuf
, 0, 8);
393 memcpy(tmp_cmdbuf
, cmdbuffer
, cmd_len
);
394 _rtl92ee_fill_h2c_command(hw
, element_id
, cmd_len
, (u8
*)&tmp_cmdbuf
);
397 void rtl92ee_firmware_selfreset(struct ieee80211_hw
*hw
)
400 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
402 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
403 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
& (~BIT(0))));
405 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
406 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
& (~BIT(2))));
410 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
411 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
| BIT(0)));
413 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
414 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
| BIT(2)));
416 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
417 " _8051Reset92E(): 8051 reset success .\n");
420 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw
*hw
, u8 mode
)
422 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
423 u8 u1_h2c_set_pwrmode
[H2C_92E_PWEMODE_LENGTH
] = { 0 };
424 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
425 u8 rlbm
, power_state
= 0, byte5
= 0;
426 u8 awake_intvl
; /* DTIM = (awake_intvl - 1) */
427 struct rtl_btc_ops
*btc_ops
= rtlpriv
->btcoexist
.btc_ops
;
428 bool bt_ctrl_lps
= (rtlpriv
->cfg
->ops
->get_btc_status() ?
429 btc_ops
->btc_is_bt_ctrl_lps(rtlpriv
) : false);
431 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_DMESG
, "FW LPS mode = %d (coex:%d)\n",
443 case FW_PS_DTIM_MODE
:
445 awake_intvl
= ppsc
->reg_max_lps_awakeintvl
;
446 /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
447 * is only used in swlps.
456 if (rtlpriv
->mac80211
.p2p
) {
461 if (mode
== FW_PS_ACTIVE_MODE
) {
463 power_state
= FW_PWR_STATE_ACTIVE
;
466 byte5
= btc_ops
->btc_get_lps_val(rtlpriv
);
467 power_state
= btc_ops
->btc_get_rpwm_val(rtlpriv
);
469 if ((rlbm
== 2) && (byte5
& BIT(4))) {
470 /* Keep awake interval to 1 to prevent from
471 * decreasing coex performance
478 power_state
= FW_PWR_STATE_RF_OFF
;
482 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode
, ((mode
) ? 1 : 0));
483 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode
, rlbm
);
484 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode
,
485 (rtlpriv
->mac80211
.p2p
) ?
487 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode
,
489 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode
, 0);
490 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode
, power_state
);
491 SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode
, byte5
);
493 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_DMESG
,
494 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
495 u1_h2c_set_pwrmode
, H2C_92E_PWEMODE_LENGTH
);
496 if (rtlpriv
->cfg
->ops
->get_btc_status())
497 btc_ops
->btc_record_pwr_mode(rtlpriv
, u1_h2c_set_pwrmode
,
498 H2C_92E_PWEMODE_LENGTH
);
499 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_SETPWRMODE
, H2C_92E_PWEMODE_LENGTH
,
503 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw
*hw
, u8 mstatus
)
505 u8 parm
[3] = { 0 , 0 , 0 };
506 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
507 * bit1=0-->update Media Status to MACID
508 * bit1=1-->update Media Status from MACID to MACID_End
509 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
513 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm
, mstatus
);
514 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm
, 0);
516 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_MSRRPT
, 3, parm
);
519 #define BEACON_PG 0 /* ->1 */
522 #define PROBERSP_PG 4 /* ->5 */
523 #define QOS_NULL_PG 6
524 #define BT_QOS_NULL_PG 7
526 #define TOTAL_RESERVED_PKT_LEN 1024
528 static u8 reserved_page_packet
[TOTAL_RESERVED_PKT_LEN
] = {
530 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
531 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
532 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
535 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
536 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
537 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
538 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
539 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
543 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
544 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
545 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
548 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
567 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
585 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
586 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 /* page 4 probe_resp */
602 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
603 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
604 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
605 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
606 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
607 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
608 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
609 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
610 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
611 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
612 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
616 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 /* page 5 probe_resp */
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
628 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 /* page 6 qos null data */
634 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
635 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
636 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
646 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 /* page 7 BT-qos null data */
652 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
653 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
654 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw
*hw
, bool b_dl_finished
)
676 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
677 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
678 struct sk_buff
*skb
= NULL
;
681 u8 u1rsvdpageloc
[5] = { 0 };
690 /*---------------------------------------------------------
692 *---------------------------------------------------------
694 beacon
= &reserved_page_packet
[BEACON_PG
* 128];
695 SET_80211_HDR_ADDRESS2(beacon
, mac
->mac_addr
);
696 SET_80211_HDR_ADDRESS3(beacon
, mac
->bssid
);
698 /*-------------------------------------------------------
700 *--------------------------------------------------------
702 p_pspoll
= &reserved_page_packet
[PSPOLL_PG
* 128];
703 SET_80211_PS_POLL_AID(p_pspoll
, (mac
->assoc_id
| 0xc000));
704 SET_80211_PS_POLL_BSSID(p_pspoll
, mac
->bssid
);
705 SET_80211_PS_POLL_TA(p_pspoll
, mac
->mac_addr
);
707 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc
, PSPOLL_PG
);
709 /*--------------------------------------------------------
711 *---------------------------------------------------------
713 nullfunc
= &reserved_page_packet
[NULL_PG
* 128];
714 SET_80211_HDR_ADDRESS1(nullfunc
, mac
->bssid
);
715 SET_80211_HDR_ADDRESS2(nullfunc
, mac
->mac_addr
);
716 SET_80211_HDR_ADDRESS3(nullfunc
, mac
->bssid
);
718 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc
, NULL_PG
);
720 /*---------------------------------------------------------
722 *----------------------------------------------------------
724 p_probersp
= &reserved_page_packet
[PROBERSP_PG
* 128];
725 SET_80211_HDR_ADDRESS1(p_probersp
, mac
->bssid
);
726 SET_80211_HDR_ADDRESS2(p_probersp
, mac
->mac_addr
);
727 SET_80211_HDR_ADDRESS3(p_probersp
, mac
->bssid
);
729 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc
, PROBERSP_PG
);
731 /*---------------------------------------------------------
733 *----------------------------------------------------------
735 qosnull
= &reserved_page_packet
[QOS_NULL_PG
* 128];
736 SET_80211_HDR_ADDRESS1(qosnull
, mac
->bssid
);
737 SET_80211_HDR_ADDRESS2(qosnull
, mac
->mac_addr
);
738 SET_80211_HDR_ADDRESS3(qosnull
, mac
->bssid
);
740 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc
, QOS_NULL_PG
);
742 /*---------------------------------------------------------
743 * (6) BT QoS null data
744 *----------------------------------------------------------
746 btqosnull
= &reserved_page_packet
[BT_QOS_NULL_PG
* 128];
747 SET_80211_HDR_ADDRESS1(btqosnull
, mac
->bssid
);
748 SET_80211_HDR_ADDRESS2(btqosnull
, mac
->mac_addr
);
749 SET_80211_HDR_ADDRESS3(btqosnull
, mac
->bssid
);
751 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc
, BT_QOS_NULL_PG
);
753 totalpacketlen
= TOTAL_RESERVED_PKT_LEN
;
755 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_LOUD
,
756 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
757 &reserved_page_packet
[0], totalpacketlen
);
758 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_LOUD
,
759 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
762 skb
= dev_alloc_skb(totalpacketlen
);
763 skb_put_data(skb
, &reserved_page_packet
, totalpacketlen
);
768 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
,
769 "Set RSVD page location to Fw.\n");
770 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_LOUD
,
771 "H2C_RSVDPAGE:\n", u1rsvdpageloc
, 3);
772 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_RSVDPAGE
,
773 sizeof(u1rsvdpageloc
), u1rsvdpageloc
);
775 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
776 "Set RSVD page location to Fw FAIL!!!!!!.\n");
780 /*Shoud check FW support p2p or not.*/
781 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw
*hw
, u8 ctwindow
)
783 u8 u1_ctwindow_period
[1] = {ctwindow
};
785 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_P2P_PS_CTW_CMD
, 1, u1_ctwindow_period
);
788 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw
*hw
, u8 p2p_ps_state
)
790 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
791 struct rtl_ps_ctl
*rtlps
= rtl_psc(rtl_priv(hw
));
792 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
793 struct rtl_p2p_ps_info
*p2pinfo
= &rtlps
->p2p_ps_info
;
794 struct p2p_ps_offload_t
*p2p_ps_offload
= &rtlhal
->p2p_ps_offload
;
797 u32 start_time
, tsf_low
;
799 switch (p2p_ps_state
) {
801 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_DISABLE\n");
802 memset(p2p_ps_offload
, 0, sizeof(*p2p_ps_offload
));
805 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_ENABLE\n");
806 /* update CTWindow value. */
807 if (p2pinfo
->ctwindow
> 0) {
808 p2p_ps_offload
->ctwindow_en
= 1;
809 ctwindow
= p2pinfo
->ctwindow
;
810 rtl92ee_set_p2p_ctw_period_cmd(hw
, ctwindow
);
812 /* hw only support 2 set of NoA */
813 for (i
= 0 ; i
< p2pinfo
->noa_num
; i
++) {
814 /* To control the register setting for which NOA*/
815 rtl_write_byte(rtlpriv
, 0x5cf, (i
<< 4));
817 p2p_ps_offload
->noa0_en
= 1;
819 p2p_ps_offload
->noa1_en
= 1;
820 /* config P2P NoA Descriptor Register */
821 rtl_write_dword(rtlpriv
, 0x5E0,
822 p2pinfo
->noa_duration
[i
]);
823 rtl_write_dword(rtlpriv
, 0x5E4,
824 p2pinfo
->noa_interval
[i
]);
826 /*Get Current TSF value */
827 tsf_low
= rtl_read_dword(rtlpriv
, REG_TSFTR
);
829 start_time
= p2pinfo
->noa_start_time
[i
];
830 if (p2pinfo
->noa_count_type
[i
] != 1) {
831 while (start_time
<= (tsf_low
+ (50 * 1024))) {
832 start_time
+= p2pinfo
->noa_interval
[i
];
833 if (p2pinfo
->noa_count_type
[i
] != 255)
834 p2pinfo
->noa_count_type
[i
]--;
837 rtl_write_dword(rtlpriv
, 0x5E8, start_time
);
838 rtl_write_dword(rtlpriv
, 0x5EC,
839 p2pinfo
->noa_count_type
[i
]);
841 if ((p2pinfo
->opp_ps
== 1) || (p2pinfo
->noa_num
> 0)) {
842 /* rst p2p circuit */
843 rtl_write_byte(rtlpriv
, REG_DUAL_TSF_RST
, BIT(4));
844 p2p_ps_offload
->offload_en
= 1;
846 if (P2P_ROLE_GO
== rtlpriv
->mac80211
.p2p
) {
847 p2p_ps_offload
->role
= 1;
848 p2p_ps_offload
->allstasleep
= 0;
850 p2p_ps_offload
->role
= 0;
852 p2p_ps_offload
->discovery
= 0;
856 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_SCAN\n");
857 p2p_ps_offload
->discovery
= 1;
859 case P2P_PS_SCAN_DONE
:
860 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_SCAN_DONE\n");
861 p2p_ps_offload
->discovery
= 0;
862 p2pinfo
->p2p_ps_state
= P2P_PS_ENABLE
;
867 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_P2P_PS_OFFLOAD
, 1,
868 (u8
*)p2p_ps_offload
);
871 static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw
*hw
,
872 u8
*cmd_buf
, u8 cmd_len
)
874 u8 rate
= cmd_buf
[0] & 0x3F;
875 bool collision_state
= cmd_buf
[3] & BIT(0);
877 rtl92ee_dm_dynamic_arfb_select(hw
, rate
, collision_state
);
880 void rtl92ee_c2h_content_parsing(struct ieee80211_hw
*hw
, u8 c2h_cmd_id
,
881 u8 c2h_cmd_len
, u8
*tmp_buf
)
883 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
885 switch (c2h_cmd_id
) {
887 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
888 "[C2H], C2H_8723BE_DBG!!\n");
891 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
892 "[C2H], C2H_8192E_TXBF!!\n");
894 case C2H_8192E_TX_REPORT
:
895 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
896 "[C2H], C2H_8723BE_TX_REPORT!\n");
897 rtl_tx_report_handler(hw
, tmp_buf
, c2h_cmd_len
);
899 case C2H_8192E_BT_INFO
:
900 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
901 "[C2H], C2H_8723BE_BT_INFO!!\n");
902 rtlpriv
->btcoexist
.btc_ops
->btc_btinfo_notify(rtlpriv
, tmp_buf
,
905 case C2H_8192E_BT_MP
:
906 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
907 "[C2H], C2H_8723BE_BT_MP!!\n");
909 case C2H_8192E_RA_RPT
:
910 _rtl92ee_c2h_ra_report_handler(hw
, tmp_buf
, c2h_cmd_len
);
913 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
914 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id
);
919 void rtl92ee_c2h_packet_handler(struct ieee80211_hw
*hw
, u8
*buffer
, u8 len
)
921 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
922 u8 c2h_cmd_id
= 0, c2h_cmd_seq
= 0, c2h_cmd_len
= 0;
925 c2h_cmd_id
= buffer
[0];
926 c2h_cmd_seq
= buffer
[1];
927 c2h_cmd_len
= len
- 2;
928 tmp_buf
= buffer
+ 2;
930 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
931 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
932 c2h_cmd_id
, c2h_cmd_seq
, c2h_cmd_len
);
934 RT_PRINT_DATA(rtlpriv
, COMP_FW
, DBG_TRACE
,
935 "[C2H packet], Content Hex:\n", tmp_buf
, c2h_cmd_len
);
937 switch (c2h_cmd_id
) {
938 case C2H_8192E_BT_INFO
:
939 case C2H_8192E_BT_MP
:
940 rtl_c2hcmd_enqueue(hw
, c2h_cmd_id
, c2h_cmd_len
, tmp_buf
);
943 rtl92ee_c2h_content_parsing(hw
, c2h_cmd_id
, c2h_cmd_len
,