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 *****************************************************************************/
35 static void _rtl92ee_enable_fw_download(struct ieee80211_hw
*hw
, bool enable
)
37 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
41 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, 0x05);
43 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
+ 2);
44 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 2, tmp
& 0xf7);
46 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
47 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
& 0xfe);
51 static void _rtl92ee_fw_block_write(struct ieee80211_hw
*hw
,
52 const u8
*buffer
, u32 size
)
54 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
55 u32 blocksize
= sizeof(u32
);
56 u8
*bufferptr
= (u8
*)buffer
;
57 u32
*pu4byteptr
= (u32
*)buffer
;
58 u32 i
, offset
, blockcount
, remainsize
;
60 blockcount
= size
/ blocksize
;
61 remainsize
= size
% blocksize
;
63 for (i
= 0; i
< blockcount
; i
++) {
64 offset
= i
* blocksize
;
65 rtl_write_dword(rtlpriv
, (FW_8192C_START_ADDRESS
+ offset
),
70 offset
= blockcount
* blocksize
;
72 for (i
= 0; i
< remainsize
; i
++) {
73 rtl_write_byte(rtlpriv
,
74 (FW_8192C_START_ADDRESS
+ offset
+ i
),
80 static void _rtl92ee_fw_page_write(struct ieee80211_hw
*hw
, u32 page
,
81 const u8
*buffer
, u32 size
)
83 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
85 u8 u8page
= (u8
)(page
& 0x07);
87 value8
= (rtl_read_byte(rtlpriv
, REG_MCUFWDL
+ 2) & 0xF8) | u8page
;
88 rtl_write_byte(rtlpriv
, (REG_MCUFWDL
+ 2), value8
);
90 _rtl92ee_fw_block_write(hw
, buffer
, size
);
93 static void _rtl92ee_fill_dummy(u8
*pfwbuf
, u32
*pfwlen
)
96 u8 remain
= (u8
)(fwlen
% 4);
98 remain
= (remain
== 0) ? 0 : (4 - remain
);
109 static void _rtl92ee_write_fw(struct ieee80211_hw
*hw
,
110 enum version_8192e version
,
111 u8
*buffer
, u32 size
)
113 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
114 u8
*bufferptr
= (u8
*)buffer
;
115 u32 pagenums
, remainsize
;
118 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "FW size is %d bytes,\n", size
);
120 _rtl92ee_fill_dummy(bufferptr
, &size
);
122 pagenums
= size
/ FW_8192C_PAGE_SIZE
;
123 remainsize
= size
% FW_8192C_PAGE_SIZE
;
126 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
127 "Page numbers should not greater then 8\n");
130 for (page
= 0; page
< pagenums
; page
++) {
131 offset
= page
* FW_8192C_PAGE_SIZE
;
132 _rtl92ee_fw_page_write(hw
, page
, (bufferptr
+ offset
),
138 offset
= pagenums
* FW_8192C_PAGE_SIZE
;
140 _rtl92ee_fw_page_write(hw
, page
, (bufferptr
+ offset
),
145 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw
*hw
)
147 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
153 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
154 } while ((counter
++ < FW_8192C_POLLING_TIMEOUT_COUNT
) &&
155 (!(value32
& FWDL_CHKSUM_RPT
)));
157 if (counter
>= FW_8192C_POLLING_TIMEOUT_COUNT
) {
158 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
159 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
164 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
165 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32
);
167 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
168 value32
|= MCUFWDL_RDY
;
169 value32
&= ~WINTINI_RDY
;
170 rtl_write_dword(rtlpriv
, REG_MCUFWDL
, value32
);
172 rtl92ee_firmware_selfreset(hw
);
176 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
177 if (value32
& WINTINI_RDY
) {
178 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
,
179 "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n",
185 udelay(FW_8192C_POLLING_DELAY
*10);
187 } while (counter
++ < FW_8192C_POLLING_TIMEOUT_COUNT
);
189 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
190 "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
197 int rtl92ee_download_fw(struct ieee80211_hw
*hw
, bool buse_wake_on_wlan_fw
)
199 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
200 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
201 struct rtl92c_firmware_header
*pfwheader
;
205 enum version_8192e version
= rtlhal
->version
;
207 if (!rtlhal
->pfirmware
)
210 pfwheader
= (struct rtl92c_firmware_header
*)rtlhal
->pfirmware
;
211 rtlhal
->fw_version
= pfwheader
->version
;
212 rtlhal
->fw_subversion
= pfwheader
->subversion
;
213 pfwdata
= (u8
*)rtlhal
->pfirmware
;
214 fwsize
= rtlhal
->fwsize
;
215 RT_TRACE(rtlpriv
, COMP_FW
, DBG_DMESG
,
216 "normal Firmware SIZE %d\n" , fwsize
);
218 if (IS_FW_HEADER_EXIST(pfwheader
)) {
219 RT_TRACE(rtlpriv
, COMP_FW
, DBG_DMESG
,
220 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
221 pfwheader
->version
, pfwheader
->signature
,
222 (int)sizeof(struct rtl92c_firmware_header
));
224 pfwdata
= pfwdata
+ sizeof(struct rtl92c_firmware_header
);
225 fwsize
= fwsize
- sizeof(struct rtl92c_firmware_header
);
227 RT_TRACE(rtlpriv
, COMP_FW
, DBG_DMESG
,
228 "Firmware no Header, Signature(%#x)\n",
229 pfwheader
->signature
);
232 if (rtlhal
->mac_func_enable
) {
233 if (rtl_read_byte(rtlpriv
, REG_MCUFWDL
) & BIT(7)) {
234 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, 0);
235 rtl92ee_firmware_selfreset(hw
);
238 _rtl92ee_enable_fw_download(hw
, true);
239 _rtl92ee_write_fw(hw
, version
, pfwdata
, fwsize
);
240 _rtl92ee_enable_fw_download(hw
, false);
242 err
= _rtl92ee_fw_free_to_go(hw
);
244 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
245 "Firmware is not ready to run!\n");
247 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
,
248 "Firmware is ready to run!\n");
254 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw
*hw
, u8 boxnum
)
256 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
260 val_hmetfr
= rtl_read_byte(rtlpriv
, REG_HMETFR
);
261 if (((val_hmetfr
>> boxnum
) & BIT(0)) == 0)
266 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw
*hw
, u8 element_id
,
267 u32 cmd_len
, u8
*cmdbuffer
)
269 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
270 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
271 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
273 u16 box_reg
= 0, box_extreg
= 0;
275 bool isfw_read
= false;
277 bool bwrite_sucess
= false;
278 u8 wait_h2c_limmit
= 100;
279 u8 boxcontent
[4], boxextcontent
[4];
280 u32 h2c_waitcounter
= 0;
284 if (ppsc
->dot11_psmode
!= EACTIVE
||
285 ppsc
->inactive_pwrstate
== ERFOFF
) {
286 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
287 "FillH2CCommand8192E(): Return because RF is off!!!\n");
291 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
, "come in\n");
293 /* 1. Prevent race condition in setting H2C cmd.
294 * (copy from MgntActSet_RF_State().)
297 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
, flag
);
298 if (rtlhal
->h2c_setinprogress
) {
299 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
300 "H2C set in progress! Wait to set..element_id(%d).\n",
303 while (rtlhal
->h2c_setinprogress
) {
304 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
,
307 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
308 "Wait 100 us (%d times)...\n",
312 if (h2c_waitcounter
> 1000)
314 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
,
317 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
319 rtlhal
->h2c_setinprogress
= true;
320 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
325 while (!bwrite_sucess
) {
326 /* 2. Find the last BOX number which has been writen. */
327 boxnum
= rtlhal
->last_hmeboxnum
;
330 box_reg
= REG_HMEBOX_0
;
331 box_extreg
= REG_HMEBOX_EXT_0
;
334 box_reg
= REG_HMEBOX_1
;
335 box_extreg
= REG_HMEBOX_EXT_1
;
338 box_reg
= REG_HMEBOX_2
;
339 box_extreg
= REG_HMEBOX_EXT_2
;
342 box_reg
= REG_HMEBOX_3
;
343 box_extreg
= REG_HMEBOX_EXT_3
;
346 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_LOUD
,
347 "switch case not process\n");
351 /* 3. Check if the box content is empty. */
353 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_CR
);
355 if (u1b_tmp
!= 0xea) {
358 if (rtl_read_byte(rtlpriv
, REG_TXDMA_STATUS
) == 0xea ||
359 rtl_read_byte(rtlpriv
, REG_TXPKT_EMPTY
) == 0xea)
360 rtl_write_byte(rtlpriv
, REG_SYS_CFG1
+ 3, 0xff);
364 wait_h2c_limmit
= 100;
365 isfw_read
= _rtl92ee_check_fw_read_last_h2c(hw
, boxnum
);
368 if (wait_h2c_limmit
== 0) {
369 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
370 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
376 _rtl92ee_check_fw_read_last_h2c(hw
, boxnum
);
377 u1b_tmp
= rtl_read_byte(rtlpriv
, 0x130);
378 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
379 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
384 /* If Fw has not read the last
385 * H2C cmd, break and give up this H2C.
388 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
389 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
393 /* 4. Fill the H2C cmd into box */
394 memset(boxcontent
, 0, sizeof(boxcontent
));
395 memset(boxextcontent
, 0, sizeof(boxextcontent
));
396 boxcontent
[0] = element_id
;
397 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
398 "Write element_id box_reg(%4x) = %2x\n",
399 box_reg
, element_id
);
405 /*boxcontent[0] &= ~(BIT(7));*/
406 memcpy((u8
*)(boxcontent
) + 1,
407 cmdbuffer
+ buf_index
, cmd_len
);
409 for (idx
= 0; idx
< 4; idx
++) {
410 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
418 /*boxcontent[0] |= (BIT(7));*/
419 memcpy((u8
*)(boxextcontent
),
420 cmdbuffer
+ buf_index
+3, cmd_len
-3);
421 memcpy((u8
*)(boxcontent
) + 1,
422 cmdbuffer
+ buf_index
, 3);
424 for (idx
= 0; idx
< 4; idx
++) {
425 rtl_write_byte(rtlpriv
, box_extreg
+ idx
,
429 for (idx
= 0; idx
< 4; idx
++) {
430 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
435 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_LOUD
,
436 "switch case not process\n");
440 bwrite_sucess
= true;
442 rtlhal
->last_hmeboxnum
= boxnum
+ 1;
443 if (rtlhal
->last_hmeboxnum
== 4)
444 rtlhal
->last_hmeboxnum
= 0;
446 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
447 "pHalData->last_hmeboxnum = %d\n",
448 rtlhal
->last_hmeboxnum
);
451 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
, flag
);
452 rtlhal
->h2c_setinprogress
= false;
453 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
455 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
, "go out\n");
458 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw
*hw
,
459 u8 element_id
, u32 cmd_len
, u8
*cmdbuffer
)
461 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
464 if (!rtlhal
->fw_ready
) {
466 "return H2C cmd because of Fw download fail!!!\n");
470 memset(tmp_cmdbuf
, 0, 8);
471 memcpy(tmp_cmdbuf
, cmdbuffer
, cmd_len
);
472 _rtl92ee_fill_h2c_command(hw
, element_id
, cmd_len
, (u8
*)&tmp_cmdbuf
);
475 void rtl92ee_firmware_selfreset(struct ieee80211_hw
*hw
)
478 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
480 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
481 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
& (~BIT(0))));
483 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
484 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
& (~BIT(2))));
488 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
489 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
| BIT(0)));
491 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
492 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
| BIT(2)));
494 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
495 " _8051Reset92E(): 8051 reset success .\n");
498 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw
*hw
, u8 mode
)
500 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
501 u8 u1_h2c_set_pwrmode
[H2C_92E_PWEMODE_LENGTH
] = { 0 };
502 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
503 u8 rlbm
, power_state
= 0;
505 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
, "FW LPS mode = %d\n", mode
);
507 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode
, ((mode
) ? 1 : 0));
508 rlbm
= 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
509 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode
, rlbm
);
510 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode
,
511 (rtlpriv
->mac80211
.p2p
) ?
513 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode
,
514 ppsc
->reg_max_lps_awakeintvl
);
515 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode
, 0);
516 if (mode
== FW_PS_ACTIVE_MODE
)
517 power_state
|= FW_PWR_STATE_ACTIVE
;
519 power_state
|= FW_PWR_STATE_RF_OFF
;
520 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode
, power_state
);
522 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_DMESG
,
523 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
524 u1_h2c_set_pwrmode
, H2C_92E_PWEMODE_LENGTH
);
525 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_SETPWRMODE
, H2C_92E_PWEMODE_LENGTH
,
529 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw
*hw
, u8 mstatus
)
531 u8 parm
[3] = { 0 , 0 , 0 };
532 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
533 * bit1=0-->update Media Status to MACID
534 * bit1=1-->update Media Status from MACID to MACID_End
535 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
539 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm
, mstatus
);
540 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm
, 0);
542 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_MSRRPT
, 3, parm
);
545 #define BEACON_PG 0 /* ->1 */
548 #define PROBERSP_PG 4 /* ->5 */
550 #define TOTAL_RESERVED_PKT_LEN 768
552 static u8 reserved_page_packet
[TOTAL_RESERVED_PKT_LEN
] = {
554 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
555 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
556 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
559 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
560 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
561 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
562 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
563 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
567 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
568 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
569 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
572 0x00, 0x50, 0xF2, 0x02, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
591 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
609 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
610 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 /* page 4 probe_resp */
626 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
627 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
628 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
629 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
630 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
631 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
632 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
633 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
634 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
635 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
636 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
640 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 /* page 5 probe_resp */
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,
662 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw
*hw
, bool b_dl_finished
)
664 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
665 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
666 struct sk_buff
*skb
= NULL
;
669 u8 u1rsvdpageloc
[5] = { 0 };
676 /*---------------------------------------------------------
678 *---------------------------------------------------------
680 beacon
= &reserved_page_packet
[BEACON_PG
* 128];
681 SET_80211_HDR_ADDRESS2(beacon
, mac
->mac_addr
);
682 SET_80211_HDR_ADDRESS3(beacon
, mac
->bssid
);
684 /*-------------------------------------------------------
686 *--------------------------------------------------------
688 p_pspoll
= &reserved_page_packet
[PSPOLL_PG
* 128];
689 SET_80211_PS_POLL_AID(p_pspoll
, (mac
->assoc_id
| 0xc000));
690 SET_80211_PS_POLL_BSSID(p_pspoll
, mac
->bssid
);
691 SET_80211_PS_POLL_TA(p_pspoll
, mac
->mac_addr
);
693 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc
, PSPOLL_PG
);
695 /*--------------------------------------------------------
697 *---------------------------------------------------------
699 nullfunc
= &reserved_page_packet
[NULL_PG
* 128];
700 SET_80211_HDR_ADDRESS1(nullfunc
, mac
->bssid
);
701 SET_80211_HDR_ADDRESS2(nullfunc
, mac
->mac_addr
);
702 SET_80211_HDR_ADDRESS3(nullfunc
, mac
->bssid
);
704 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc
, NULL_PG
);
706 /*---------------------------------------------------------
708 *----------------------------------------------------------
710 p_probersp
= &reserved_page_packet
[PROBERSP_PG
* 128];
711 SET_80211_HDR_ADDRESS1(p_probersp
, mac
->bssid
);
712 SET_80211_HDR_ADDRESS2(p_probersp
, mac
->mac_addr
);
713 SET_80211_HDR_ADDRESS3(p_probersp
, mac
->bssid
);
715 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc
, PROBERSP_PG
);
717 totalpacketlen
= TOTAL_RESERVED_PKT_LEN
;
719 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_LOUD
,
720 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
721 &reserved_page_packet
[0], totalpacketlen
);
722 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_LOUD
,
723 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
726 skb
= dev_alloc_skb(totalpacketlen
);
727 memcpy((u8
*)skb_put(skb
, totalpacketlen
),
728 &reserved_page_packet
, totalpacketlen
);
733 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
,
734 "Set RSVD page location to Fw.\n");
735 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_LOUD
,
736 "H2C_RSVDPAGE:\n", u1rsvdpageloc
, 3);
737 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_RSVDPAGE
,
738 sizeof(u1rsvdpageloc
), u1rsvdpageloc
);
740 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
741 "Set RSVD page location to Fw FAIL!!!!!!.\n");
745 /*Shoud check FW support p2p or not.*/
746 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw
*hw
, u8 ctwindow
)
748 u8 u1_ctwindow_period
[1] = {ctwindow
};
750 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_P2P_PS_CTW_CMD
, 1, u1_ctwindow_period
);
753 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw
*hw
, u8 p2p_ps_state
)
755 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
756 struct rtl_ps_ctl
*rtlps
= rtl_psc(rtl_priv(hw
));
757 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
758 struct rtl_p2p_ps_info
*p2pinfo
= &rtlps
->p2p_ps_info
;
759 struct p2p_ps_offload_t
*p2p_ps_offload
= &rtlhal
->p2p_ps_offload
;
762 u32 start_time
, tsf_low
;
764 switch (p2p_ps_state
) {
766 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_DISABLE\n");
767 memset(p2p_ps_offload
, 0, sizeof(*p2p_ps_offload
));
770 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_ENABLE\n");
771 /* update CTWindow value. */
772 if (p2pinfo
->ctwindow
> 0) {
773 p2p_ps_offload
->ctwindow_en
= 1;
774 ctwindow
= p2pinfo
->ctwindow
;
775 rtl92ee_set_p2p_ctw_period_cmd(hw
, ctwindow
);
777 /* hw only support 2 set of NoA */
778 for (i
= 0 ; i
< p2pinfo
->noa_num
; i
++) {
779 /* To control the register setting for which NOA*/
780 rtl_write_byte(rtlpriv
, 0x5cf, (i
<< 4));
782 p2p_ps_offload
->noa0_en
= 1;
784 p2p_ps_offload
->noa1_en
= 1;
785 /* config P2P NoA Descriptor Register */
786 rtl_write_dword(rtlpriv
, 0x5E0,
787 p2pinfo
->noa_duration
[i
]);
788 rtl_write_dword(rtlpriv
, 0x5E4,
789 p2pinfo
->noa_interval
[i
]);
791 /*Get Current TSF value */
792 tsf_low
= rtl_read_dword(rtlpriv
, REG_TSFTR
);
794 start_time
= p2pinfo
->noa_start_time
[i
];
795 if (p2pinfo
->noa_count_type
[i
] != 1) {
796 while (start_time
<= (tsf_low
+ (50 * 1024))) {
797 start_time
+= p2pinfo
->noa_interval
[i
];
798 if (p2pinfo
->noa_count_type
[i
] != 255)
799 p2pinfo
->noa_count_type
[i
]--;
802 rtl_write_dword(rtlpriv
, 0x5E8, start_time
);
803 rtl_write_dword(rtlpriv
, 0x5EC,
804 p2pinfo
->noa_count_type
[i
]);
806 if ((p2pinfo
->opp_ps
== 1) || (p2pinfo
->noa_num
> 0)) {
807 /* rst p2p circuit */
808 rtl_write_byte(rtlpriv
, REG_DUAL_TSF_RST
, BIT(4));
809 p2p_ps_offload
->offload_en
= 1;
811 if (P2P_ROLE_GO
== rtlpriv
->mac80211
.p2p
) {
812 p2p_ps_offload
->role
= 1;
813 p2p_ps_offload
->allstasleep
= 0;
815 p2p_ps_offload
->role
= 0;
817 p2p_ps_offload
->discovery
= 0;
821 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_SCAN\n");
822 p2p_ps_offload
->discovery
= 1;
824 case P2P_PS_SCAN_DONE
:
825 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_SCAN_DONE\n");
826 p2p_ps_offload
->discovery
= 0;
827 p2pinfo
->p2p_ps_state
= P2P_PS_ENABLE
;
832 rtl92ee_fill_h2c_cmd(hw
, H2C_92E_P2P_PS_OFFLOAD
, 1,
833 (u8
*)p2p_ps_offload
);
836 static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw
*hw
,
837 u8
*cmd_buf
, u8 cmd_len
)
839 u8 rate
= cmd_buf
[0] & 0x3F;
840 bool collision_state
= cmd_buf
[3] & BIT(0);
842 rtl92ee_dm_dynamic_arfb_select(hw
, rate
, collision_state
);
845 static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw
*hw
, u8 c2h_cmd_id
,
846 u8 c2h_cmd_len
, u8
*tmp_buf
)
848 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
850 switch (c2h_cmd_id
) {
852 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
853 "[C2H], C2H_8723BE_DBG!!\n");
856 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
857 "[C2H], C2H_8192E_TXBF!!\n");
859 case C2H_8192E_TX_REPORT
:
860 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
861 "[C2H], C2H_8723BE_TX_REPORT!\n");
863 case C2H_8192E_BT_INFO
:
864 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
865 "[C2H], C2H_8723BE_BT_INFO!!\n");
866 rtlpriv
->btcoexist
.btc_ops
->btc_btinfo_notify(rtlpriv
, tmp_buf
,
869 case C2H_8192E_BT_MP
:
870 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
871 "[C2H], C2H_8723BE_BT_MP!!\n");
873 case C2H_8192E_RA_RPT
:
874 _rtl92ee_c2h_ra_report_handler(hw
, tmp_buf
, c2h_cmd_len
);
877 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
878 "[C2H], Unkown packet!! CmdId(%#X)!\n", c2h_cmd_id
);
883 void rtl92ee_c2h_packet_handler(struct ieee80211_hw
*hw
, u8
*buffer
, u8 len
)
885 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
886 u8 c2h_cmd_id
= 0, c2h_cmd_seq
= 0, c2h_cmd_len
= 0;
889 c2h_cmd_id
= buffer
[0];
890 c2h_cmd_seq
= buffer
[1];
891 c2h_cmd_len
= len
- 2;
892 tmp_buf
= buffer
+ 2;
894 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
895 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
896 c2h_cmd_id
, c2h_cmd_seq
, c2h_cmd_len
);
898 RT_PRINT_DATA(rtlpriv
, COMP_FW
, DBG_TRACE
,
899 "[C2H packet], Content Hex:\n", tmp_buf
, c2h_cmd_len
);
901 _rtl92ee_c2h_content_parsing(hw
, c2h_cmd_id
, c2h_cmd_len
, tmp_buf
);