1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2013 Realtek Corporation.*/
13 static void _rtl88e_enable_fw_download(struct ieee80211_hw
*hw
, bool enable
)
15 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
19 tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
20 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, tmp
| 0x04);
22 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
23 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
| 0x01);
25 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
+ 2);
26 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 2, tmp
& 0xf7);
28 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
29 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
& 0xfe);
31 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 1, 0x00);
35 static void _rtl88e_write_fw(struct ieee80211_hw
*hw
,
36 enum version_8188e version
, u8
*buffer
, u32 size
)
38 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
39 u8
*bufferptr
= (u8
*)buffer
;
40 u32 pagenums
, remainsize
;
43 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "FW size is %d bytes,\n", size
);
45 rtl_fill_dummy(bufferptr
, &size
);
47 pagenums
= size
/ FW_8192C_PAGE_SIZE
;
48 remainsize
= size
% FW_8192C_PAGE_SIZE
;
51 pr_err("Page numbers should not greater then 8\n");
53 for (page
= 0; page
< pagenums
; page
++) {
54 offset
= page
* FW_8192C_PAGE_SIZE
;
55 rtl_fw_page_write(hw
, page
, (bufferptr
+ offset
),
60 offset
= pagenums
* FW_8192C_PAGE_SIZE
;
62 rtl_fw_page_write(hw
, page
, (bufferptr
+ offset
), remainsize
);
66 static int _rtl88e_fw_free_to_go(struct ieee80211_hw
*hw
)
68 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
74 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
75 } while ((counter
++ < FW_8192C_POLLING_TIMEOUT_COUNT
) &&
76 (!(value32
& FWDL_CHKSUM_RPT
)));
78 if (counter
>= FW_8192C_POLLING_TIMEOUT_COUNT
) {
79 pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n",
83 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
84 value32
|= MCUFWDL_RDY
;
85 value32
&= ~WINTINI_RDY
;
86 rtl_write_dword(rtlpriv
, REG_MCUFWDL
, value32
);
88 rtl88e_firmware_selfreset(hw
);
92 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
93 if (value32
& WINTINI_RDY
)
96 udelay(FW_8192C_POLLING_DELAY
);
98 } while (counter
++ < FW_8192C_POLLING_TIMEOUT_COUNT
);
100 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n",
107 int rtl88e_download_fw(struct ieee80211_hw
*hw
,
108 bool buse_wake_on_wlan_fw
)
110 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
111 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
112 struct rtlwifi_firmware_header
*pfwheader
;
116 enum version_8188e version
= rtlhal
->version
;
118 if (!rtlhal
->pfirmware
)
121 pfwheader
= (struct rtlwifi_firmware_header
*)rtlhal
->pfirmware
;
122 rtlhal
->fw_version
= le16_to_cpu(pfwheader
->version
);
123 rtlhal
->fw_subversion
= pfwheader
->subversion
;
124 pfwdata
= rtlhal
->pfirmware
;
125 fwsize
= rtlhal
->fwsize
;
126 RT_TRACE(rtlpriv
, COMP_FW
, DBG_DMESG
,
127 "normal Firmware SIZE %d\n", fwsize
);
129 if (IS_FW_HEADER_EXIST(pfwheader
)) {
130 RT_TRACE(rtlpriv
, COMP_FW
, DBG_DMESG
,
131 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
132 pfwheader
->version
, pfwheader
->signature
,
133 (int)sizeof(struct rtlwifi_firmware_header
));
135 pfwdata
= pfwdata
+ sizeof(struct rtlwifi_firmware_header
);
136 fwsize
= fwsize
- sizeof(struct rtlwifi_firmware_header
);
139 if (rtl_read_byte(rtlpriv
, REG_MCUFWDL
) & BIT(7)) {
140 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, 0);
141 rtl88e_firmware_selfreset(hw
);
143 _rtl88e_enable_fw_download(hw
, true);
144 _rtl88e_write_fw(hw
, version
, pfwdata
, fwsize
);
145 _rtl88e_enable_fw_download(hw
, false);
147 err
= _rtl88e_fw_free_to_go(hw
);
149 pr_err("Firmware is not ready to run!\n");
154 static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw
*hw
, u8 boxnum
)
156 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
159 val_hmetfr
= rtl_read_byte(rtlpriv
, REG_HMETFR
);
160 if (((val_hmetfr
>> boxnum
) & BIT(0)) == 0)
165 static void _rtl88e_fill_h2c_command(struct ieee80211_hw
*hw
,
166 u8 element_id
, u32 cmd_len
,
169 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
170 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
172 u16 box_reg
= 0, box_extreg
= 0;
174 bool isfw_read
= false;
176 bool write_sucess
= false;
177 u8 wait_h2c_limmit
= 100;
178 u8 wait_writeh2c_limit
= 100;
179 u8 boxcontent
[4], boxextcontent
[4];
180 u32 h2c_waitcounter
= 0;
184 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
, "come in\n");
187 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
, flag
);
188 if (rtlhal
->h2c_setinprogress
) {
189 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
190 "H2C set in progress! Wait to set..element_id(%d).\n",
193 while (rtlhal
->h2c_setinprogress
) {
194 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
,
197 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
198 "Wait 100 us (%d times)...\n",
202 if (h2c_waitcounter
> 1000)
204 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
,
207 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
209 rtlhal
->h2c_setinprogress
= true;
210 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
215 while (!write_sucess
) {
216 wait_writeh2c_limit
--;
217 if (wait_writeh2c_limit
== 0) {
218 pr_err("Write H2C fail because no trigger for FW INT!\n");
222 boxnum
= rtlhal
->last_hmeboxnum
;
225 box_reg
= REG_HMEBOX_0
;
226 box_extreg
= REG_HMEBOX_EXT_0
;
229 box_reg
= REG_HMEBOX_1
;
230 box_extreg
= REG_HMEBOX_EXT_1
;
233 box_reg
= REG_HMEBOX_2
;
234 box_extreg
= REG_HMEBOX_EXT_2
;
237 box_reg
= REG_HMEBOX_3
;
238 box_extreg
= REG_HMEBOX_EXT_3
;
241 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_LOUD
,
242 "switch case %#x not processed\n", boxnum
);
245 isfw_read
= _rtl88e_check_fw_read_last_h2c(hw
, boxnum
);
248 if (wait_h2c_limmit
== 0) {
249 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
250 "Waiting too long for FW read clear HMEBox(%d)!\n",
257 isfw_read
= _rtl88e_check_fw_read_last_h2c(hw
, boxnum
);
258 u1b_tmp
= rtl_read_byte(rtlpriv
, 0x130);
259 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
260 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
265 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
266 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
271 memset(boxcontent
, 0, sizeof(boxcontent
));
272 memset(boxextcontent
, 0, sizeof(boxextcontent
));
273 boxcontent
[0] = element_id
;
274 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
275 "Write element_id box_reg(%4x) = %2x\n",
276 box_reg
, element_id
);
282 /*boxcontent[0] &= ~(BIT(7));*/
283 memcpy((u8
*)(boxcontent
) + 1,
284 cmd_b
+ buf_index
, cmd_len
);
286 for (idx
= 0; idx
< 4; idx
++) {
287 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
295 /*boxcontent[0] |= (BIT(7));*/
296 memcpy((u8
*)(boxextcontent
),
297 cmd_b
+ buf_index
+3, cmd_len
-3);
298 memcpy((u8
*)(boxcontent
) + 1,
299 cmd_b
+ buf_index
, 3);
301 for (idx
= 0; idx
< 2; idx
++) {
302 rtl_write_byte(rtlpriv
, box_extreg
+ idx
,
306 for (idx
= 0; idx
< 4; idx
++) {
307 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
312 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_LOUD
,
313 "switch case %#x not processed\n", cmd_len
);
319 rtlhal
->last_hmeboxnum
= boxnum
+ 1;
320 if (rtlhal
->last_hmeboxnum
== 4)
321 rtlhal
->last_hmeboxnum
= 0;
323 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
324 "pHalData->last_hmeboxnum = %d\n",
325 rtlhal
->last_hmeboxnum
);
328 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
, flag
);
329 rtlhal
->h2c_setinprogress
= false;
330 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
332 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
, "go out\n");
335 void rtl88e_fill_h2c_cmd(struct ieee80211_hw
*hw
,
336 u8 element_id
, u32 cmd_len
, u8
*cmdbuffer
)
338 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
341 if (!rtlhal
->fw_ready
) {
343 "rtl8188ee: error H2C cmd because of Fw download fail!!!\n");
347 memset(tmp_cmdbuf
, 0, 8);
348 memcpy(tmp_cmdbuf
, cmdbuffer
, cmd_len
);
349 _rtl88e_fill_h2c_command(hw
, element_id
, cmd_len
, (u8
*)&tmp_cmdbuf
);
354 void rtl88e_firmware_selfreset(struct ieee80211_hw
*hw
)
357 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
359 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+1);
360 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+1, (u1b_tmp
& (~BIT(2))));
361 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+1, (u1b_tmp
| BIT(2)));
362 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
363 "8051Reset88E(): 8051 reset success\n");
367 void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw
*hw
, u8 mode
)
369 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
370 u8 u1_h2c_set_pwrmode
[H2C_88E_PWEMODE_LENGTH
] = { 0 };
371 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
372 u8 rlbm
, power_state
= 0;
373 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
, "FW LPS mode = %d\n", mode
);
375 set_h2ccmd_pwrmode_parm_mode(u1_h2c_set_pwrmode
, ((mode
) ? 1 : 0));
376 rlbm
= 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/
377 set_h2ccmd_pwrmode_parm_rlbm(u1_h2c_set_pwrmode
, rlbm
);
378 set_h2ccmd_pwrmode_parm_smart_ps(u1_h2c_set_pwrmode
,
379 (rtlpriv
->mac80211
.p2p
) ? ppsc
->smart_ps
: 1);
380 set_h2ccmd_pwrmode_parm_awake_interval(u1_h2c_set_pwrmode
,
381 ppsc
->reg_max_lps_awakeintvl
);
382 set_h2ccmd_pwrmode_parm_all_queue_uapsd(u1_h2c_set_pwrmode
, 0);
383 if (mode
== FW_PS_ACTIVE_MODE
)
384 power_state
|= FW_PWR_STATE_ACTIVE
;
386 power_state
|= FW_PWR_STATE_RF_OFF
;
388 set_h2ccmd_pwrmode_parm_pwr_state(u1_h2c_set_pwrmode
, power_state
);
390 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_DMESG
,
391 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
392 u1_h2c_set_pwrmode
, H2C_88E_PWEMODE_LENGTH
);
393 rtl88e_fill_h2c_cmd(hw
, H2C_88E_SETPWRMODE
,
394 H2C_88E_PWEMODE_LENGTH
, u1_h2c_set_pwrmode
);
397 void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw
*hw
, u8 mstatus
)
399 u8 u1_joinbssrpt_parm
[1] = { 0 };
401 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm
, mstatus
);
403 rtl88e_fill_h2c_cmd(hw
, H2C_88E_JOINBSSRPT
, 1, u1_joinbssrpt_parm
);
406 void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw
*hw
,
407 u8 ap_offload_enable
)
409 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
410 u8 u1_apoffload_parm
[H2C_88E_AP_OFFLOAD_LENGTH
] = { 0 };
412 SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm
, ap_offload_enable
);
413 SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm
, mac
->hiddenssid
);
414 SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm
, 0);
416 rtl88e_fill_h2c_cmd(hw
, H2C_88E_AP_OFFLOAD
,
417 H2C_88E_AP_OFFLOAD_LENGTH
, u1_apoffload_parm
);
421 #define BEACON_PG 0 /* ->1 */
424 #define PROBERSP_PG 4 /* ->5 */
426 #define TOTAL_RESERVED_PKT_LEN 768
428 static u8 reserved_page_packet
[TOTAL_RESERVED_PKT_LEN
] = {
430 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
431 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
432 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
435 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
436 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
437 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
438 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
439 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
440 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
444 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
467 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
480 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
485 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
486 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
498 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
501 /* page 4 probe_resp */
502 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
503 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
504 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
505 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
506 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
507 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
508 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
509 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
510 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
511 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
512 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
516 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 /* page 5 probe_resp */
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw
*hw
, bool b_dl_finished
)
540 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
541 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
542 struct sk_buff
*skb
= NULL
;
545 u8 u1rsvdpageloc
[5] = { 0 };
552 /*---------------------------------------------------------
554 *---------------------------------------------------------
556 beacon
= &reserved_page_packet
[BEACON_PG
* 128];
557 SET_80211_HDR_ADDRESS2(beacon
, mac
->mac_addr
);
558 SET_80211_HDR_ADDRESS3(beacon
, mac
->bssid
);
560 /*-------------------------------------------------------
562 *--------------------------------------------------------
564 p_pspoll
= &reserved_page_packet
[PSPOLL_PG
* 128];
565 SET_80211_PS_POLL_AID(p_pspoll
, (mac
->assoc_id
| 0xc000));
566 SET_80211_PS_POLL_BSSID(p_pspoll
, mac
->bssid
);
567 SET_80211_PS_POLL_TA(p_pspoll
, mac
->mac_addr
);
569 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc
, PSPOLL_PG
);
571 /*--------------------------------------------------------
573 *---------------------------------------------------------
575 nullfunc
= &reserved_page_packet
[NULL_PG
* 128];
576 SET_80211_HDR_ADDRESS1(nullfunc
, mac
->bssid
);
577 SET_80211_HDR_ADDRESS2(nullfunc
, mac
->mac_addr
);
578 SET_80211_HDR_ADDRESS3(nullfunc
, mac
->bssid
);
580 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc
, NULL_PG
);
582 /*---------------------------------------------------------
584 *----------------------------------------------------------
586 p_probersp
= &reserved_page_packet
[PROBERSP_PG
* 128];
587 SET_80211_HDR_ADDRESS1(p_probersp
, mac
->bssid
);
588 SET_80211_HDR_ADDRESS2(p_probersp
, mac
->mac_addr
);
589 SET_80211_HDR_ADDRESS3(p_probersp
, mac
->bssid
);
591 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc
, PROBERSP_PG
);
593 totalpacketlen
= TOTAL_RESERVED_PKT_LEN
;
595 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_LOUD
,
596 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
597 &reserved_page_packet
[0], totalpacketlen
);
598 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_DMESG
,
599 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
602 skb
= dev_alloc_skb(totalpacketlen
);
605 skb_put_data(skb
, &reserved_page_packet
, totalpacketlen
);
607 rtstatus
= rtl_cmd_send_packet(hw
, skb
);
613 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
,
614 "Set RSVD page location to Fw.\n");
615 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_DMESG
,
616 "H2C_RSVDPAGE:\n", u1rsvdpageloc
, 3);
617 rtl88e_fill_h2c_cmd(hw
, H2C_88E_RSVDPAGE
,
618 sizeof(u1rsvdpageloc
), u1rsvdpageloc
);
620 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
621 "Set RSVD page location to Fw FAIL!!!!!!.\n");
624 /*Should check FW support p2p or not.*/
625 static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw
*hw
, u8 ctwindow
)
627 u8 u1_ctwindow_period
[1] = { ctwindow
};
629 rtl88e_fill_h2c_cmd(hw
, H2C_88E_P2P_PS_CTW_CMD
, 1, u1_ctwindow_period
);
633 void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw
*hw
, u8 p2p_ps_state
)
635 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
636 struct rtl_ps_ctl
*rtlps
= rtl_psc(rtl_priv(hw
));
637 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
638 struct rtl_p2p_ps_info
*p2pinfo
= &(rtlps
->p2p_ps_info
);
639 struct p2p_ps_offload_t
*p2p_ps_offload
= &rtlhal
->p2p_ps_offload
;
642 u32 start_time
, tsf_low
;
644 switch (p2p_ps_state
) {
646 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_DISABLE\n");
647 memset(p2p_ps_offload
, 0, sizeof(*p2p_ps_offload
));
650 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_ENABLE\n");
651 /* update CTWindow value. */
652 if (p2pinfo
->ctwindow
> 0) {
653 p2p_ps_offload
->ctwindow_en
= 1;
654 ctwindow
= p2pinfo
->ctwindow
;
655 rtl88e_set_p2p_ctw_period_cmd(hw
, ctwindow
);
658 /* hw only support 2 set of NoA */
659 for (i
= 0 ; i
< p2pinfo
->noa_num
; i
++) {
660 /* To control the register setting for which NOA*/
661 rtl_write_byte(rtlpriv
, 0x5cf, (i
<< 4));
663 p2p_ps_offload
->noa0_en
= 1;
665 p2p_ps_offload
->noa1_en
= 1;
667 /* config P2P NoA Descriptor Register */
668 rtl_write_dword(rtlpriv
, 0x5E0,
669 p2pinfo
->noa_duration
[i
]);
670 rtl_write_dword(rtlpriv
, 0x5E4,
671 p2pinfo
->noa_interval
[i
]);
673 /*Get Current TSF value */
674 tsf_low
= rtl_read_dword(rtlpriv
, REG_TSFTR
);
676 start_time
= p2pinfo
->noa_start_time
[i
];
677 if (p2pinfo
->noa_count_type
[i
] != 1) {
678 while (start_time
<= (tsf_low
+(50*1024))) {
679 start_time
+= p2pinfo
->noa_interval
[i
];
680 if (p2pinfo
->noa_count_type
[i
] != 255)
681 p2pinfo
->noa_count_type
[i
]--;
684 rtl_write_dword(rtlpriv
, 0x5E8, start_time
);
685 rtl_write_dword(rtlpriv
, 0x5EC,
686 p2pinfo
->noa_count_type
[i
]);
689 if ((p2pinfo
->opp_ps
== 1) || (p2pinfo
->noa_num
> 0)) {
690 /* rst p2p circuit */
691 rtl_write_byte(rtlpriv
, REG_DUAL_TSF_RST
, BIT(4));
693 p2p_ps_offload
->offload_en
= 1;
695 if (P2P_ROLE_GO
== rtlpriv
->mac80211
.p2p
) {
696 p2p_ps_offload
->role
= 1;
697 p2p_ps_offload
->allstasleep
= -1;
699 p2p_ps_offload
->role
= 0;
702 p2p_ps_offload
->discovery
= 0;
706 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_SCAN\n");
707 p2p_ps_offload
->discovery
= 1;
709 case P2P_PS_SCAN_DONE
:
710 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_SCAN_DONE\n");
711 p2p_ps_offload
->discovery
= 0;
712 p2pinfo
->p2p_ps_state
= P2P_PS_ENABLE
;
718 rtl88e_fill_h2c_cmd(hw
, H2C_88E_P2P_PS_OFFLOAD
, 1,
719 (u8
*)p2p_ps_offload
);