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  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25 
26 #include "../wifi.h"
27 #include "../pci.h"
28 #include "../base.h"
29 #include "../core.h"
30 #include "reg.h"
31 #include "def.h"
32 #include "fw.h"
33 
34 static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable)
35 {
36 	struct rtl_priv *rtlpriv = rtl_priv(hw);
37 	u8 tmp;
38 
39 	if (enable) {
40 		tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
41 		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
42 
43 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
44 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
45 
46 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
47 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
48 	} else {
49 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
50 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
51 
52 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
53 	}
54 }
55 
56 static void _rtl88e_fw_block_write(struct ieee80211_hw *hw,
57 				   const u8 *buffer, u32 size)
58 {
59 	struct rtl_priv *rtlpriv = rtl_priv(hw);
60 	u32 blocksize = sizeof(u32);
61 	u8 *bufferptr = (u8 *)buffer;
62 	u32 *pu4BytePtr = (u32 *)buffer;
63 	u32 i, offset, blockcount, remainsize;
64 
65 	blockcount = size / blocksize;
66 	remainsize = size % blocksize;
67 
68 	for (i = 0; i < blockcount; i++) {
69 		offset = i * blocksize;
70 		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
71 				*(pu4BytePtr + i));
72 	}
73 
74 	if (remainsize) {
75 		offset = blockcount * blocksize;
76 		bufferptr += offset;
77 		for (i = 0; i < remainsize; i++) {
78 			rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
79 						 offset + i), *(bufferptr + i));
80 		}
81 	}
82 }
83 
84 static void _rtl88e_fw_page_write(struct ieee80211_hw *hw,
85 				  u32 page, const u8 *buffer, u32 size)
86 {
87 	struct rtl_priv *rtlpriv = rtl_priv(hw);
88 	u8 value8;
89 	u8 u8page = (u8) (page & 0x07);
90 
91 	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
92 
93 	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
94 	_rtl88e_fw_block_write(hw, buffer, size);
95 }
96 
97 static void _rtl88e_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
98 {
99 	u32 fwlen = *pfwlen;
100 	u8 remain = (u8) (fwlen % 4);
101 
102 	remain = (remain == 0) ? 0 : (4 - remain);
103 
104 	while (remain > 0) {
105 		pfwbuf[fwlen] = 0;
106 		fwlen++;
107 		remain--;
108 	}
109 
110 	*pfwlen = fwlen;
111 }
112 
113 static void _rtl88e_write_fw(struct ieee80211_hw *hw,
114 			     enum version_8188e version, u8 *buffer, u32 size)
115 {
116 	struct rtl_priv *rtlpriv = rtl_priv(hw);
117 	u8 *bufferptr = (u8 *)buffer;
118 	u32 pagenums, remainsize;
119 	u32 page, offset;
120 
121 	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
122 
123 	_rtl88e_fill_dummy(bufferptr, &size);
124 
125 	pagenums = size / FW_8192C_PAGE_SIZE;
126 	remainsize = size % FW_8192C_PAGE_SIZE;
127 
128 	if (pagenums > 8) {
129 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
130 			 "Page numbers should not greater then 8\n");
131 	}
132 
133 	for (page = 0; page < pagenums; page++) {
134 		offset = page * FW_8192C_PAGE_SIZE;
135 		_rtl88e_fw_page_write(hw, page, (bufferptr + offset),
136 				      FW_8192C_PAGE_SIZE);
137 	}
138 
139 	if (remainsize) {
140 		offset = pagenums * FW_8192C_PAGE_SIZE;
141 		page = pagenums;
142 		_rtl88e_fw_page_write(hw, page, (bufferptr + offset),
143 				      remainsize);
144 	}
145 }
146 
147 static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw)
148 {
149 	struct rtl_priv *rtlpriv = rtl_priv(hw);
150 	int err = -EIO;
151 	u32 counter = 0;
152 	u32 value32;
153 
154 	do {
155 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
156 	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
157 		 (!(value32 & FWDL_CHKSUM_RPT)));
158 
159 	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
160 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
161 			 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
162 			  value32);
163 		goto exit;
164 	}
165 
166 	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
167 		 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
168 
169 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
170 	value32 |= MCUFWDL_RDY;
171 	value32 &= ~WINTINI_RDY;
172 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
173 
174 	rtl88e_firmware_selfreset(hw);
175 	counter = 0;
176 
177 	do {
178 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
179 		if (value32 & WINTINI_RDY) {
180 			RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
181 				 "Polling FW ready success!! REG_MCUFWDL:0x%08x.\n",
182 				  value32);
183 			err = 0;
184 			goto exit;
185 		}
186 
187 		udelay(FW_8192C_POLLING_DELAY);
188 
189 	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
190 
191 	RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
192 		 "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
193 
194 exit:
195 	return err;
196 }
197 
198 int rtl88e_download_fw(struct ieee80211_hw *hw,
199 		       bool buse_wake_on_wlan_fw)
200 {
201 	struct rtl_priv *rtlpriv = rtl_priv(hw);
202 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
203 	struct rtlwifi_firmware_header *pfwheader;
204 	u8 *pfwdata;
205 	u32 fwsize;
206 	int err;
207 	enum version_8188e version = rtlhal->version;
208 
209 	if (!rtlhal->pfirmware)
210 		return 1;
211 
212 	pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
213 	pfwdata = rtlhal->pfirmware;
214 	fwsize = rtlhal->fwsize;
215 	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
216 		 "normal Firmware SIZE %d\n", fwsize);
217 
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 rtlwifi_firmware_header));
223 
224 		pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
225 		fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
226 	}
227 
228 	if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
229 		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
230 		rtl88e_firmware_selfreset(hw);
231 	}
232 	_rtl88e_enable_fw_download(hw, true);
233 	_rtl88e_write_fw(hw, version, pfwdata, fwsize);
234 	_rtl88e_enable_fw_download(hw, false);
235 
236 	err = _rtl88e_fw_free_to_go(hw);
237 	if (err) {
238 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
239 			 "Firmware is not ready to run!\n");
240 	} else {
241 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
242 			 "Firmware is ready to run!\n");
243 	}
244 
245 	return 0;
246 }
247 
248 static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
249 {
250 	struct rtl_priv *rtlpriv = rtl_priv(hw);
251 	u8 val_hmetfr;
252 
253 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
254 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
255 		return true;
256 	return false;
257 }
258 
259 static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw,
260 				     u8 element_id, u32 cmd_len,
261 				     u8 *cmd_b)
262 {
263 	struct rtl_priv *rtlpriv = rtl_priv(hw);
264 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
265 	u8 boxnum;
266 	u16 box_reg = 0, box_extreg = 0;
267 	u8 u1b_tmp;
268 	bool isfw_read = false;
269 	u8 buf_index = 0;
270 	bool write_sucess = false;
271 	u8 wait_h2c_limmit = 100;
272 	u8 wait_writeh2c_limit = 100;
273 	u8 boxcontent[4], boxextcontent[4];
274 	u32 h2c_waitcounter = 0;
275 	unsigned long flag;
276 	u8 idx;
277 
278 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
279 
280 	while (true) {
281 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
282 		if (rtlhal->h2c_setinprogress) {
283 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
284 				 "H2C set in progress! Wait to set..element_id(%d).\n",
285 				 element_id);
286 
287 			while (rtlhal->h2c_setinprogress) {
288 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
289 						       flag);
290 				h2c_waitcounter++;
291 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
292 					 "Wait 100 us (%d times)...\n",
293 					 h2c_waitcounter);
294 				udelay(100);
295 
296 				if (h2c_waitcounter > 1000)
297 					return;
298 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
299 						  flag);
300 			}
301 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
302 		} else {
303 			rtlhal->h2c_setinprogress = true;
304 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
305 			break;
306 		}
307 	}
308 
309 	while (!write_sucess) {
310 		wait_writeh2c_limit--;
311 		if (wait_writeh2c_limit == 0) {
312 			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
313 				 "Write H2C fail because no trigger for FW INT!\n");
314 			break;
315 		}
316 
317 		boxnum = rtlhal->last_hmeboxnum;
318 		switch (boxnum) {
319 		case 0:
320 			box_reg = REG_HMEBOX_0;
321 			box_extreg = REG_HMEBOX_EXT_0;
322 			break;
323 		case 1:
324 			box_reg = REG_HMEBOX_1;
325 			box_extreg = REG_HMEBOX_EXT_1;
326 			break;
327 		case 2:
328 			box_reg = REG_HMEBOX_2;
329 			box_extreg = REG_HMEBOX_EXT_2;
330 			break;
331 		case 3:
332 			box_reg = REG_HMEBOX_3;
333 			box_extreg = REG_HMEBOX_EXT_3;
334 			break;
335 		default:
336 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
337 				 "switch case %#x not processed\n", boxnum);
338 			break;
339 		}
340 		isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
341 		while (!isfw_read) {
342 			wait_h2c_limmit--;
343 			if (wait_h2c_limmit == 0) {
344 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
345 					 "Waiting too long for FW read clear HMEBox(%d)!\n",
346 					 boxnum);
347 				break;
348 			}
349 
350 			udelay(10);
351 
352 			isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
353 			u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
354 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
355 				 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
356 				 boxnum, u1b_tmp);
357 		}
358 
359 		if (!isfw_read) {
360 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
361 				 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
362 				 boxnum);
363 			break;
364 		}
365 
366 		memset(boxcontent, 0, sizeof(boxcontent));
367 		memset(boxextcontent, 0, sizeof(boxextcontent));
368 		boxcontent[0] = element_id;
369 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
370 			 "Write element_id box_reg(%4x) = %2x\n",
371 			 box_reg, element_id);
372 
373 		switch (cmd_len) {
374 		case 1:
375 		case 2:
376 		case 3:
377 			/*boxcontent[0] &= ~(BIT(7));*/
378 			memcpy((u8 *)(boxcontent) + 1,
379 			       cmd_b + buf_index, cmd_len);
380 
381 			for (idx = 0; idx < 4; idx++) {
382 				rtl_write_byte(rtlpriv, box_reg + idx,
383 					       boxcontent[idx]);
384 			}
385 			break;
386 		case 4:
387 		case 5:
388 		case 6:
389 		case 7:
390 			/*boxcontent[0] |= (BIT(7));*/
391 			memcpy((u8 *)(boxextcontent),
392 			       cmd_b + buf_index+3, cmd_len-3);
393 			memcpy((u8 *)(boxcontent) + 1,
394 			       cmd_b + buf_index, 3);
395 
396 			for (idx = 0; idx < 2; idx++) {
397 				rtl_write_byte(rtlpriv, box_extreg + idx,
398 					       boxextcontent[idx]);
399 			}
400 
401 			for (idx = 0; idx < 4; idx++) {
402 				rtl_write_byte(rtlpriv, box_reg + idx,
403 					       boxcontent[idx]);
404 			}
405 			break;
406 		default:
407 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
408 				 "switch case %#x not processed\n", cmd_len);
409 			break;
410 		}
411 
412 		write_sucess = true;
413 
414 		rtlhal->last_hmeboxnum = boxnum + 1;
415 		if (rtlhal->last_hmeboxnum == 4)
416 			rtlhal->last_hmeboxnum = 0;
417 
418 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
419 			 "pHalData->last_hmeboxnum  = %d\n",
420 			  rtlhal->last_hmeboxnum);
421 	}
422 
423 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
424 	rtlhal->h2c_setinprogress = false;
425 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
426 
427 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
428 }
429 
430 void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw,
431 			 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
432 {
433 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
434 	u32 tmp_cmdbuf[2];
435 
436 	if (!rtlhal->fw_ready) {
437 		RT_ASSERT(false,
438 			  "return H2C cmd because of Fw download fail!!!\n");
439 		return;
440 	}
441 
442 	memset(tmp_cmdbuf, 0, 8);
443 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
444 	_rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
445 
446 	return;
447 }
448 
449 void rtl88e_firmware_selfreset(struct ieee80211_hw *hw)
450 {
451 	u8 u1b_tmp;
452 	struct rtl_priv *rtlpriv = rtl_priv(hw);
453 
454 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
455 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2))));
456 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2)));
457 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
458 		 "8051Reset88E(): 8051 reset success\n");
459 
460 }
461 
462 void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
463 {
464 	struct rtl_priv *rtlpriv = rtl_priv(hw);
465 	u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 };
466 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
467 	u8 rlbm, power_state = 0;
468 	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
469 
470 	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
471 	rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/
472 	SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
473 	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
474 		(rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
475 	SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
476 		ppsc->reg_max_lps_awakeintvl);
477 	SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
478 	if (mode == FW_PS_ACTIVE_MODE)
479 		power_state |= FW_PWR_STATE_ACTIVE;
480 	else
481 		power_state |= FW_PWR_STATE_RF_OFF;
482 
483 	SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
484 
485 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
486 		      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
487 		      u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH);
488 	rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE,
489 			    H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
490 }
491 
492 void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
493 {
494 	u8 u1_joinbssrpt_parm[1] = { 0 };
495 
496 	SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
497 
498 	rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm);
499 }
500 
501 void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
502 				   u8 ap_offload_enable)
503 {
504 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
505 	u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 };
506 
507 	SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
508 	SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
509 	SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
510 
511 	rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD,
512 			    H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm);
513 
514 }
515 
516 #define BEACON_PG		0 /* ->1 */
517 #define PSPOLL_PG		2
518 #define NULL_PG			3
519 #define PROBERSP_PG		4 /* ->5 */
520 
521 #define TOTAL_RESERVED_PKT_LEN	768
522 
523 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
524 	/* page 0 beacon */
525 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
526 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
527 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
528 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
530 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
531 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
532 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
533 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
534 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
535 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
539 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 
542 	/* page 1 beacon */
543 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 	0x00, 0x00, 0x00, 0x00, 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 	0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
556 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 
560 	/* page 2  ps-poll */
561 	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
562 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
563 	0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
574 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
575 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 
578 	/* page 3  null */
579 	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
580 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
581 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
582 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,
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 	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
592 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
593 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 
596 	/* page 4  probe_resp */
597 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
598 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
599 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
600 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
601 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
602 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
603 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
604 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
605 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
606 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
607 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
611 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 
614 	/* page 5  probe_resp */
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 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 };
632 
633 void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
634 {
635 	struct rtl_priv *rtlpriv = rtl_priv(hw);
636 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
637 	struct sk_buff *skb = NULL;
638 	u32 totalpacketlen;
639 	bool rtstatus;
640 	u8 u1rsvdpageloc[5] = { 0 };
641 	bool b_dlok = false;
642 	u8 *beacon;
643 	u8 *p_pspoll;
644 	u8 *nullfunc;
645 	u8 *p_probersp;
646 
647 	/*---------------------------------------------------------
648 	 *			(1) beacon
649 	 *---------------------------------------------------------
650 	 */
651 	beacon = &reserved_page_packet[BEACON_PG * 128];
652 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
653 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
654 
655 	/*-------------------------------------------------------
656 	 *			(2) ps-poll
657 	 *--------------------------------------------------------
658 	 */
659 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
660 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
661 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
662 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
663 
664 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
665 
666 	/*--------------------------------------------------------
667 	 *			(3) null data
668 	 *---------------------------------------------------------
669 	 */
670 	nullfunc = &reserved_page_packet[NULL_PG * 128];
671 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
672 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
673 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
674 
675 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
676 
677 	/*---------------------------------------------------------
678 	 *			(4) probe response
679 	 *----------------------------------------------------------
680 	 */
681 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
682 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
683 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
684 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
685 
686 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
687 
688 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
689 
690 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
691 		      "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
692 		      &reserved_page_packet[0], totalpacketlen);
693 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
694 		      "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
695 		      u1rsvdpageloc, 3);
696 
697 	skb = dev_alloc_skb(totalpacketlen);
698 	memcpy(skb_put(skb, totalpacketlen),
699 	       &reserved_page_packet, totalpacketlen);
700 
701 	rtstatus = rtl_cmd_send_packet(hw, skb);
702 
703 	if (rtstatus)
704 		b_dlok = true;
705 
706 	if (b_dlok) {
707 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
708 			 "Set RSVD page location to Fw.\n");
709 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
710 			      "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
711 		rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE,
712 				    sizeof(u1rsvdpageloc), u1rsvdpageloc);
713 	} else
714 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
715 			 "Set RSVD page location to Fw FAIL!!!!!!.\n");
716 }
717 
718 /*Should check FW support p2p or not.*/
719 static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
720 {
721 	u8 u1_ctwindow_period[1] = { ctwindow};
722 
723 	rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
724 
725 }
726 
727 void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
728 {
729 	struct rtl_priv *rtlpriv = rtl_priv(hw);
730 	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
731 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
732 	struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
733 	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
734 	u8	i;
735 	u16	ctwindow;
736 	u32	start_time, tsf_low;
737 
738 	switch (p2p_ps_state) {
739 	case P2P_PS_DISABLE:
740 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
741 		memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
742 		break;
743 	case P2P_PS_ENABLE:
744 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
745 		/* update CTWindow value. */
746 		if (p2pinfo->ctwindow > 0) {
747 			p2p_ps_offload->ctwindow_en = 1;
748 			ctwindow = p2pinfo->ctwindow;
749 			rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow);
750 		}
751 
752 		/* hw only support 2 set of NoA */
753 		for (i = 0 ; i < p2pinfo->noa_num; i++) {
754 			/* To control the register setting for which NOA*/
755 			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
756 			if (i == 0)
757 				p2p_ps_offload->noa0_en = 1;
758 			else
759 				p2p_ps_offload->noa1_en = 1;
760 
761 			/* config P2P NoA Descriptor Register */
762 			rtl_write_dword(rtlpriv, 0x5E0,
763 					p2pinfo->noa_duration[i]);
764 			rtl_write_dword(rtlpriv, 0x5E4,
765 					p2pinfo->noa_interval[i]);
766 
767 			/*Get Current TSF value */
768 			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
769 
770 			start_time = p2pinfo->noa_start_time[i];
771 			if (p2pinfo->noa_count_type[i] != 1) {
772 				while (start_time <= (tsf_low+(50*1024))) {
773 					start_time += p2pinfo->noa_interval[i];
774 					if (p2pinfo->noa_count_type[i] != 255)
775 						p2pinfo->noa_count_type[i]--;
776 				}
777 			}
778 			rtl_write_dword(rtlpriv, 0x5E8, start_time);
779 			rtl_write_dword(rtlpriv, 0x5EC,
780 					p2pinfo->noa_count_type[i]);
781 		}
782 
783 		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
784 			/* rst p2p circuit */
785 			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
786 
787 			p2p_ps_offload->offload_en = 1;
788 
789 			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
790 				p2p_ps_offload->role = 1;
791 				p2p_ps_offload->allstasleep = -1;
792 			} else {
793 				p2p_ps_offload->role = 0;
794 			}
795 
796 			p2p_ps_offload->discovery = 0;
797 		}
798 		break;
799 	case P2P_PS_SCAN:
800 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
801 		p2p_ps_offload->discovery = 1;
802 		break;
803 	case P2P_PS_SCAN_DONE:
804 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
805 		p2p_ps_offload->discovery = 0;
806 		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
807 		break;
808 	default:
809 		break;
810 	}
811 
812 	rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1,
813 			    (u8 *)p2p_ps_offload);
814 
815 }
816