xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2014  Realtek Corporation.*/
3 
4 #include "../wifi.h"
5 #include "../pci.h"
6 #include "../base.h"
7 #include "../core.h"
8 #include "../efuse.h"
9 #include "reg.h"
10 #include "def.h"
11 #include "fw.h"
12 #include "dm.h"
13 
14 static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
15 {
16 	struct rtl_priv *rtlpriv = rtl_priv(hw);
17 	u8 tmp;
18 
19 	if (enable) {
20 		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
21 
22 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
23 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
24 	} else {
25 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
26 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
27 	}
28 }
29 
30 static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
31 			      enum version_8192e version,
32 			      u8 *buffer, u32 size)
33 {
34 	struct rtl_priv *rtlpriv = rtl_priv(hw);
35 	u8 *bufferptr = (u8 *)buffer;
36 	u32 pagenums, remainsize;
37 	u32 page, offset;
38 
39 	rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
40 
41 	rtl_fill_dummy(bufferptr, &size);
42 
43 	pagenums = size / FW_8192C_PAGE_SIZE;
44 	remainsize = size % FW_8192C_PAGE_SIZE;
45 
46 	if (pagenums > 8)
47 		pr_err("Page numbers should not greater then 8\n");
48 
49 	for (page = 0; page < pagenums; page++) {
50 		offset = page * FW_8192C_PAGE_SIZE;
51 		rtl_fw_page_write(hw, page, (bufferptr + offset),
52 				  FW_8192C_PAGE_SIZE);
53 		udelay(2);
54 	}
55 
56 	if (remainsize) {
57 		offset = pagenums * FW_8192C_PAGE_SIZE;
58 		page = pagenums;
59 		rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
60 	}
61 }
62 
63 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
64 {
65 	struct rtl_priv *rtlpriv = rtl_priv(hw);
66 	int err = -EIO;
67 	u32 counter = 0;
68 	u32 value32;
69 
70 	do {
71 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
72 	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
73 		 (!(value32 & FWDL_CHKSUM_RPT)));
74 
75 	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
76 		pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
77 		       value32);
78 		goto exit;
79 	}
80 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
81 	value32 |= MCUFWDL_RDY;
82 	value32 &= ~WINTINI_RDY;
83 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
84 
85 	rtl92ee_firmware_selfreset(hw);
86 	counter = 0;
87 
88 	do {
89 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
90 		if (value32 & WINTINI_RDY)
91 			return 0;
92 
93 		udelay(FW_8192C_POLLING_DELAY*10);
94 
95 	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
96 
97 	pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
98 	       value32, counter);
99 
100 exit:
101 	return err;
102 }
103 
104 int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
105 {
106 	struct rtl_priv *rtlpriv = rtl_priv(hw);
107 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
108 	struct rtlwifi_firmware_header *pfwheader;
109 	u8 *pfwdata;
110 	u32 fwsize;
111 	enum version_8192e version = rtlhal->version;
112 
113 	if (!rtlhal->pfirmware)
114 		return 1;
115 
116 	pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
117 	rtlhal->fw_version = le16_to_cpu(pfwheader->version);
118 	rtlhal->fw_subversion = pfwheader->subversion;
119 	pfwdata = (u8 *)rtlhal->pfirmware;
120 	fwsize = rtlhal->fwsize;
121 	rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
122 		"normal Firmware SIZE %d\n", fwsize);
123 
124 	if (IS_FW_HEADER_EXIST(pfwheader)) {
125 		rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
126 			"Firmware Version(%d), Signature(%#x),Size(%d)\n",
127 			pfwheader->version, pfwheader->signature,
128 			(int)sizeof(struct rtlwifi_firmware_header));
129 
130 		pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
131 		fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
132 	} else {
133 		rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
134 			"Firmware no Header, Signature(%#x)\n",
135 			pfwheader->signature);
136 	}
137 
138 	if (rtlhal->mac_func_enable) {
139 		if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
140 			rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
141 			rtl92ee_firmware_selfreset(hw);
142 		}
143 	}
144 	_rtl92ee_enable_fw_download(hw, true);
145 	_rtl92ee_write_fw(hw, version, pfwdata, fwsize);
146 	_rtl92ee_enable_fw_download(hw, false);
147 
148 	return _rtl92ee_fw_free_to_go(hw);
149 }
150 
151 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
152 {
153 	struct rtl_priv *rtlpriv = rtl_priv(hw);
154 	u8 val_hmetfr;
155 	bool result = false;
156 
157 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
158 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
159 		result = true;
160 	return result;
161 }
162 
163 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
164 				      u32 cmd_len, u8 *cmdbuffer)
165 {
166 	struct rtl_priv *rtlpriv = rtl_priv(hw);
167 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
168 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
169 	u8 boxnum;
170 	u16 box_reg = 0, box_extreg = 0;
171 	u8 u1b_tmp;
172 	bool isfw_read = false;
173 	u8 buf_index = 0;
174 	bool bwrite_sucess = false;
175 	u8 wait_h2c_limmit = 100;
176 	u8 boxcontent[4], boxextcontent[4];
177 	u32 h2c_waitcounter = 0;
178 	unsigned long flag;
179 	u8 idx;
180 
181 	if (ppsc->dot11_psmode != EACTIVE ||
182 	    ppsc->inactive_pwrstate == ERFOFF) {
183 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
184 			"FillH2CCommand8192E(): Return because RF is off!!!\n");
185 		return;
186 	}
187 
188 	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
189 
190 	/* 1. Prevent race condition in setting H2C cmd.
191 	 * (copy from MgntActSet_RF_State().)
192 	 */
193 	while (true) {
194 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
195 		if (rtlhal->h2c_setinprogress) {
196 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
197 				"H2C set in progress! Wait to set..element_id(%d).\n",
198 				element_id);
199 
200 			while (rtlhal->h2c_setinprogress) {
201 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
202 						       flag);
203 				h2c_waitcounter++;
204 				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
205 					"Wait 100 us (%d times)...\n",
206 					h2c_waitcounter);
207 				udelay(100);
208 
209 				if (h2c_waitcounter > 1000)
210 					return;
211 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
212 						  flag);
213 			}
214 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
215 		} else {
216 			rtlhal->h2c_setinprogress = true;
217 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
218 			break;
219 		}
220 	}
221 
222 	while (!bwrite_sucess) {
223 		/* 2. Find the last BOX number which has been writen. */
224 		boxnum = rtlhal->last_hmeboxnum;
225 		switch (boxnum) {
226 		case 0:
227 			box_reg = REG_HMEBOX_0;
228 			box_extreg = REG_HMEBOX_EXT_0;
229 			break;
230 		case 1:
231 			box_reg = REG_HMEBOX_1;
232 			box_extreg = REG_HMEBOX_EXT_1;
233 			break;
234 		case 2:
235 			box_reg = REG_HMEBOX_2;
236 			box_extreg = REG_HMEBOX_EXT_2;
237 			break;
238 		case 3:
239 			box_reg = REG_HMEBOX_3;
240 			box_extreg = REG_HMEBOX_EXT_3;
241 			break;
242 		default:
243 			rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
244 				"switch case %#x not processed\n", boxnum);
245 			break;
246 		}
247 
248 		/* 3. Check if the box content is empty. */
249 		isfw_read = false;
250 		u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
251 
252 		if (u1b_tmp != 0xea) {
253 			isfw_read = true;
254 		} else {
255 			if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
256 			    rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
257 				rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
258 		}
259 
260 		if (isfw_read) {
261 			wait_h2c_limmit = 100;
262 			isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
263 			while (!isfw_read) {
264 				wait_h2c_limmit--;
265 				if (wait_h2c_limmit == 0) {
266 					rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
267 						"Waiting too long for FW read clear HMEBox(%d)!!!\n",
268 						boxnum);
269 					break;
270 				}
271 				udelay(10);
272 				isfw_read =
273 				  _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
274 				u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
275 				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
276 					"Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
277 					boxnum, u1b_tmp);
278 			}
279 		}
280 
281 		/* If Fw has not read the last
282 		 * H2C cmd, break and give up this H2C.
283 		 */
284 		if (!isfw_read) {
285 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
286 				"Write H2C reg BOX[%d] fail,Fw don't read.\n",
287 				boxnum);
288 			break;
289 		}
290 		/* 4. Fill the H2C cmd into box */
291 		memset(boxcontent, 0, sizeof(boxcontent));
292 		memset(boxextcontent, 0, sizeof(boxextcontent));
293 		boxcontent[0] = element_id;
294 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
295 			"Write element_id box_reg(%4x) = %2x\n",
296 			box_reg, element_id);
297 
298 		switch (cmd_len) {
299 		case 1:
300 		case 2:
301 		case 3:
302 			/*boxcontent[0] &= ~(BIT(7));*/
303 			memcpy((u8 *)(boxcontent) + 1,
304 			       cmdbuffer + buf_index, cmd_len);
305 
306 			for (idx = 0; idx < 4; idx++) {
307 				rtl_write_byte(rtlpriv, box_reg + idx,
308 					       boxcontent[idx]);
309 			}
310 			break;
311 		case 4:
312 		case 5:
313 		case 6:
314 		case 7:
315 			/*boxcontent[0] |= (BIT(7));*/
316 			memcpy((u8 *)(boxextcontent),
317 			       cmdbuffer + buf_index+3, cmd_len-3);
318 			memcpy((u8 *)(boxcontent) + 1,
319 			       cmdbuffer + buf_index, 3);
320 
321 			for (idx = 0; idx < 4; idx++) {
322 				rtl_write_byte(rtlpriv, box_extreg + idx,
323 					       boxextcontent[idx]);
324 			}
325 
326 			for (idx = 0; idx < 4; idx++) {
327 				rtl_write_byte(rtlpriv, box_reg + idx,
328 					       boxcontent[idx]);
329 			}
330 			break;
331 		default:
332 			rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
333 				"switch case %#x not processed\n", cmd_len);
334 			break;
335 		}
336 
337 		bwrite_sucess = true;
338 
339 		rtlhal->last_hmeboxnum = boxnum + 1;
340 		if (rtlhal->last_hmeboxnum == 4)
341 			rtlhal->last_hmeboxnum = 0;
342 
343 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
344 			"pHalData->last_hmeboxnum  = %d\n",
345 			rtlhal->last_hmeboxnum);
346 	}
347 
348 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
349 	rtlhal->h2c_setinprogress = false;
350 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
351 
352 	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
353 }
354 
355 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
356 			  u8 element_id, u32 cmd_len, u8 *cmdbuffer)
357 {
358 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
359 	u32 tmp_cmdbuf[2];
360 
361 	if (!rtlhal->fw_ready) {
362 		WARN_ONCE(true,
363 			  "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
364 		return;
365 	}
366 
367 	memset(tmp_cmdbuf, 0, 8);
368 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
369 	_rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
370 }
371 
372 void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
373 {
374 	u8 u1b_tmp;
375 	struct rtl_priv *rtlpriv = rtl_priv(hw);
376 
377 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
378 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
379 
380 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
381 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
382 
383 	udelay(50);
384 
385 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
386 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
387 
388 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
389 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
390 
391 	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
392 		"  _8051Reset92E(): 8051 reset success .\n");
393 }
394 
395 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
396 {
397 	struct rtl_priv *rtlpriv = rtl_priv(hw);
398 	u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
399 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
400 	u8 rlbm, power_state = 0, byte5 = 0;
401 	u8 awake_intvl;	/* DTIM = (awake_intvl - 1) */
402 	struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
403 	bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
404 			    btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
405 	bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
406 			  btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
407 
408 	if (bt_ctrl_lps)
409 		mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
410 
411 	rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
412 		mode, bt_ctrl_lps);
413 
414 	switch (mode) {
415 	case FW_PS_MIN_MODE:
416 		rlbm = 0;
417 		awake_intvl = 2;
418 		break;
419 	case FW_PS_MAX_MODE:
420 		rlbm = 1;
421 		awake_intvl = 2;
422 		break;
423 	case FW_PS_DTIM_MODE:
424 		rlbm = 2;
425 		awake_intvl = ppsc->reg_max_lps_awakeintvl;
426 		/* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
427 		 * is only used in swlps.
428 		 */
429 		break;
430 	default:
431 		rlbm = 2;
432 		awake_intvl = 4;
433 		break;
434 	}
435 
436 	if (rtlpriv->mac80211.p2p) {
437 		awake_intvl = 2;
438 		rlbm = 1;
439 	}
440 
441 	if (mode == FW_PS_ACTIVE_MODE) {
442 		byte5 = 0x40;
443 		power_state = FW_PWR_STATE_ACTIVE;
444 	} else {
445 		if (bt_ctrl_lps) {
446 			byte5 = btc_ops->btc_get_lps_val(rtlpriv);
447 			power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
448 
449 			if ((rlbm == 2) && (byte5 & BIT(4))) {
450 				/* Keep awake interval to 1 to prevent from
451 				 * decreasing coex performance
452 				 */
453 				awake_intvl = 2;
454 				rlbm = 2;
455 			}
456 		} else {
457 			byte5 = 0x40;
458 			power_state = FW_PWR_STATE_RF_OFF;
459 		}
460 	}
461 
462 	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
463 	SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
464 	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
465 					 bt_ctrl_lps ? 0 :
466 					 ((rtlpriv->mac80211.p2p) ?
467 					  ppsc->smart_ps : 1));
468 	SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
469 					       awake_intvl);
470 	SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
471 	SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
472 	SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
473 
474 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
475 		      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
476 		      u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
477 	if (rtlpriv->cfg->ops->get_btc_status())
478 		btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
479 					     H2C_92E_PWEMODE_LENGTH);
480 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
481 			     u1_h2c_set_pwrmode);
482 }
483 
484 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
485 {
486 	u8 parm[3] = { 0 , 0 , 0 };
487 	/* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
488 	 *          bit1=0-->update Media Status to MACID
489 	 *          bit1=1-->update Media Status from MACID to MACID_End
490 	 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
491 	 * parm[2]: MACID_End
492 	 */
493 
494 	SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
495 	SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
496 
497 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
498 }
499 
500 #define BEACON_PG		0 /* ->1 */
501 #define PSPOLL_PG		2
502 #define NULL_PG			3
503 #define PROBERSP_PG		4 /* ->5 */
504 #define QOS_NULL_PG		6
505 #define BT_QOS_NULL_PG	7
506 
507 #define TOTAL_RESERVED_PKT_LEN	1024
508 
509 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
510 	/* page 0 beacon */
511 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
512 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
513 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
514 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 	0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
516 	0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
517 	0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
518 	0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
519 	0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
520 	0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
524 	0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
525 	0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
526 	0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
527 
528 	/* page 1 beacon */
529 	0x00, 0x50, 0xF2, 0x02, 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,
536 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 	0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
541 	0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
542 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 
546 	/* page 2  ps-poll */
547 	0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
548 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
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 	0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
559 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
560 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 
564 	/* page 3  null */
565 	0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
566 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
567 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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 	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 	0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
577 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
578 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 
582 	/* page 4  probe_resp */
583 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
584 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
585 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
586 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
587 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
588 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
589 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
590 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
591 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
592 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
593 	0x03, 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 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
597 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 
600 	/* page 5  probe_resp */
601 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
609 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
610 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 
614 	/* page 6 qos null data */
615 	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
616 	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
617 	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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 	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
627 	0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
628 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 
632 	/* page 7 BT-qos null data */
633 	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
634 	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
635 	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
636 	0x00, 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 	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 	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 };
654 
655 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
656 {
657 	struct rtl_priv *rtlpriv = rtl_priv(hw);
658 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
659 	struct sk_buff *skb = NULL;
660 	bool rtstatus;
661 	u32 totalpacketlen;
662 	u8 u1rsvdpageloc[5] = { 0 };
663 	bool b_dlok = false;
664 
665 	u8 *beacon;
666 	u8 *p_pspoll;
667 	u8 *nullfunc;
668 	u8 *p_probersp;
669 	u8 *qosnull;
670 	u8 *btqosnull;
671 	/*---------------------------------------------------------
672 	 *			(1) beacon
673 	 *---------------------------------------------------------
674 	 */
675 	beacon = &reserved_page_packet[BEACON_PG * 128];
676 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
677 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
678 
679 	/*-------------------------------------------------------
680 	 *			(2) ps-poll
681 	 *--------------------------------------------------------
682 	 */
683 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
684 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
685 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
686 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
687 
688 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
689 
690 	/*--------------------------------------------------------
691 	 *			(3) null data
692 	 *---------------------------------------------------------
693 	 */
694 	nullfunc = &reserved_page_packet[NULL_PG * 128];
695 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
696 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
697 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
698 
699 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
700 
701 	/*---------------------------------------------------------
702 	 *			(4) probe response
703 	 *----------------------------------------------------------
704 	 */
705 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
706 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
707 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
708 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
709 
710 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
711 
712 	/*---------------------------------------------------------
713 	 *			(5) QoS null data
714 	 *----------------------------------------------------------
715 	 */
716 	qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
717 	SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
718 	SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
719 	SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
720 
721 	SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
722 
723 	/*---------------------------------------------------------
724 	 *			(6) BT QoS null data
725 	 *----------------------------------------------------------
726 	 */
727 	btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
728 	SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
729 	SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
730 	SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
731 
732 	SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
733 
734 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
735 
736 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
737 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
738 		      &reserved_page_packet[0], totalpacketlen);
739 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
740 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
741 		      u1rsvdpageloc, 3);
742 
743 	skb = dev_alloc_skb(totalpacketlen);
744 	if (!skb)
745 		return;
746 	skb_put_data(skb, &reserved_page_packet, totalpacketlen);
747 
748 	rtstatus = rtl_cmd_send_packet(hw, skb);
749 	if (rtstatus)
750 		b_dlok = true;
751 
752 	if (b_dlok) {
753 		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
754 			"Set RSVD page location to Fw.\n");
755 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
756 			      "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
757 		rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
758 				     sizeof(u1rsvdpageloc), u1rsvdpageloc);
759 	} else {
760 		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
761 			"Set RSVD page location to Fw FAIL!!!!!!.\n");
762 	}
763 }
764 
765 /*Shoud check FW support p2p or not.*/
766 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
767 {
768 	u8 u1_ctwindow_period[1] = {ctwindow};
769 
770 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
771 }
772 
773 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
774 {
775 	struct rtl_priv *rtlpriv = rtl_priv(hw);
776 	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
777 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
778 	struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
779 	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
780 	u8 i;
781 	u16 ctwindow;
782 	u32 start_time, tsf_low;
783 
784 	switch (p2p_ps_state) {
785 	case P2P_PS_DISABLE:
786 		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
787 		memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
788 		break;
789 	case P2P_PS_ENABLE:
790 		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
791 		/* update CTWindow value. */
792 		if (p2pinfo->ctwindow > 0) {
793 			p2p_ps_offload->ctwindow_en = 1;
794 			ctwindow = p2pinfo->ctwindow;
795 			rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
796 		}
797 		/* hw only support 2 set of NoA */
798 		for (i = 0 ; i < p2pinfo->noa_num ; i++) {
799 			/* To control the register setting for which NOA*/
800 			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
801 			if (i == 0)
802 				p2p_ps_offload->noa0_en = 1;
803 			else
804 				p2p_ps_offload->noa1_en = 1;
805 			/* config P2P NoA Descriptor Register */
806 			rtl_write_dword(rtlpriv, 0x5E0,
807 					p2pinfo->noa_duration[i]);
808 			rtl_write_dword(rtlpriv, 0x5E4,
809 					p2pinfo->noa_interval[i]);
810 
811 			/*Get Current TSF value */
812 			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
813 
814 			start_time = p2pinfo->noa_start_time[i];
815 			if (p2pinfo->noa_count_type[i] != 1) {
816 				while (start_time <= (tsf_low + (50 * 1024))) {
817 					start_time += p2pinfo->noa_interval[i];
818 					if (p2pinfo->noa_count_type[i] != 255)
819 						p2pinfo->noa_count_type[i]--;
820 				}
821 			}
822 			rtl_write_dword(rtlpriv, 0x5E8, start_time);
823 			rtl_write_dword(rtlpriv, 0x5EC,
824 					p2pinfo->noa_count_type[i]);
825 		}
826 		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
827 			/* rst p2p circuit */
828 			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
829 			p2p_ps_offload->offload_en = 1;
830 
831 			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
832 				p2p_ps_offload->role = 1;
833 				p2p_ps_offload->allstasleep = 0;
834 			} else {
835 				p2p_ps_offload->role = 0;
836 			}
837 			p2p_ps_offload->discovery = 0;
838 		}
839 		break;
840 	case P2P_PS_SCAN:
841 		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
842 		p2p_ps_offload->discovery = 1;
843 		break;
844 	case P2P_PS_SCAN_DONE:
845 		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
846 		p2p_ps_offload->discovery = 0;
847 		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
848 		break;
849 	default:
850 		break;
851 	}
852 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
853 			     (u8 *)p2p_ps_offload);
854 }
855 
856 void rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
857 				   u8 *cmd_buf, u8 cmd_len)
858 {
859 	u8 rate = cmd_buf[0] & 0x3F;
860 	bool collision_state = cmd_buf[3] & BIT(0);
861 
862 	rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
863 }
864