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