xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c (revision 16cefa449c9ced7006860d5427b9595782248ca4)
1f1d2b4d3SLarry Finger /******************************************************************************
2f1d2b4d3SLarry Finger  *
3f1d2b4d3SLarry Finger  * Copyright(c) 2009-2014  Realtek Corporation.
4f1d2b4d3SLarry Finger  *
5f1d2b4d3SLarry Finger  * This program is free software; you can redistribute it and/or modify it
6f1d2b4d3SLarry Finger  * under the terms of version 2 of the GNU General Public License as
7f1d2b4d3SLarry Finger  * published by the Free Software Foundation.
8f1d2b4d3SLarry Finger  *
9f1d2b4d3SLarry Finger  * This program is distributed in the hope that it will be useful, but WITHOUT
10f1d2b4d3SLarry Finger  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11f1d2b4d3SLarry Finger  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12f1d2b4d3SLarry Finger  * more details.
13f1d2b4d3SLarry Finger  *
14f1d2b4d3SLarry Finger  * The full GNU General Public License is included in this distribution in the
15f1d2b4d3SLarry Finger  * file called LICENSE.
16f1d2b4d3SLarry Finger  *
17f1d2b4d3SLarry Finger  * Contact Information:
18f1d2b4d3SLarry Finger  * wlanfae <wlanfae@realtek.com>
19f1d2b4d3SLarry Finger  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20f1d2b4d3SLarry Finger  * Hsinchu 300, Taiwan.
21f1d2b4d3SLarry Finger  *
22f1d2b4d3SLarry Finger  * Larry Finger <Larry.Finger@lwfinger.net>
23f1d2b4d3SLarry Finger  *
24f1d2b4d3SLarry Finger  *****************************************************************************/
25f1d2b4d3SLarry Finger 
26f1d2b4d3SLarry Finger #include "../wifi.h"
27f1d2b4d3SLarry Finger #include "../pci.h"
28f1d2b4d3SLarry Finger #include "../base.h"
29f1d2b4d3SLarry Finger #include "../core.h"
3089d32c90SLarry Finger #include "../efuse.h"
31f1d2b4d3SLarry Finger #include "reg.h"
32f1d2b4d3SLarry Finger #include "def.h"
33f1d2b4d3SLarry Finger #include "fw.h"
34f1d2b4d3SLarry Finger #include "dm.h"
35f1d2b4d3SLarry Finger 
36f1d2b4d3SLarry Finger static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
37f1d2b4d3SLarry Finger {
38f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
39f1d2b4d3SLarry Finger 	u8 tmp;
40f1d2b4d3SLarry Finger 
41f1d2b4d3SLarry Finger 	if (enable) {
42f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
43f1d2b4d3SLarry Finger 
44f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
45f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
46f1d2b4d3SLarry Finger 	} else {
47f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
48f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
49f1d2b4d3SLarry Finger 	}
50f1d2b4d3SLarry Finger }
51f1d2b4d3SLarry Finger 
52f1d2b4d3SLarry Finger static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
53f1d2b4d3SLarry Finger 			      enum version_8192e version,
54f1d2b4d3SLarry Finger 			      u8 *buffer, u32 size)
55f1d2b4d3SLarry Finger {
56f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
57f1d2b4d3SLarry Finger 	u8 *bufferptr = (u8 *)buffer;
58f1d2b4d3SLarry Finger 	u32 pagenums, remainsize;
59f1d2b4d3SLarry Finger 	u32 page, offset;
60f1d2b4d3SLarry Finger 
61f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size);
62f1d2b4d3SLarry Finger 
6389d32c90SLarry Finger 	rtl_fill_dummy(bufferptr, &size);
64f1d2b4d3SLarry Finger 
65f1d2b4d3SLarry Finger 	pagenums = size / FW_8192C_PAGE_SIZE;
66f1d2b4d3SLarry Finger 	remainsize = size % FW_8192C_PAGE_SIZE;
67f1d2b4d3SLarry Finger 
68a44f59d6SLarry Finger 	if (pagenums > 8)
69a44f59d6SLarry Finger 		pr_err("Page numbers should not greater then 8\n");
70f1d2b4d3SLarry Finger 
71f1d2b4d3SLarry Finger 	for (page = 0; page < pagenums; page++) {
72f1d2b4d3SLarry Finger 		offset = page * FW_8192C_PAGE_SIZE;
7389d32c90SLarry Finger 		rtl_fw_page_write(hw, page, (bufferptr + offset),
74f1d2b4d3SLarry Finger 				  FW_8192C_PAGE_SIZE);
75f1d2b4d3SLarry Finger 		udelay(2);
76f1d2b4d3SLarry Finger 	}
77f1d2b4d3SLarry Finger 
78f1d2b4d3SLarry Finger 	if (remainsize) {
79f1d2b4d3SLarry Finger 		offset = pagenums * FW_8192C_PAGE_SIZE;
80f1d2b4d3SLarry Finger 		page = pagenums;
8189d32c90SLarry Finger 		rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
82f1d2b4d3SLarry Finger 	}
83f1d2b4d3SLarry Finger }
84f1d2b4d3SLarry Finger 
85f1d2b4d3SLarry Finger static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
86f1d2b4d3SLarry Finger {
87f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
88f1d2b4d3SLarry Finger 	int err = -EIO;
89f1d2b4d3SLarry Finger 	u32 counter = 0;
90f1d2b4d3SLarry Finger 	u32 value32;
91f1d2b4d3SLarry Finger 
92f1d2b4d3SLarry Finger 	do {
93f1d2b4d3SLarry Finger 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
94f1d2b4d3SLarry Finger 	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
95f1d2b4d3SLarry Finger 		 (!(value32 & FWDL_CHKSUM_RPT)));
96f1d2b4d3SLarry Finger 
97f1d2b4d3SLarry Finger 	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
98a44f59d6SLarry Finger 		pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
99f1d2b4d3SLarry Finger 		       value32);
100f1d2b4d3SLarry Finger 		goto exit;
101f1d2b4d3SLarry Finger 	}
102f1d2b4d3SLarry Finger 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
103f1d2b4d3SLarry Finger 	value32 |= MCUFWDL_RDY;
104f1d2b4d3SLarry Finger 	value32 &= ~WINTINI_RDY;
105f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
106f1d2b4d3SLarry Finger 
107f1d2b4d3SLarry Finger 	rtl92ee_firmware_selfreset(hw);
108f1d2b4d3SLarry Finger 	counter = 0;
109f1d2b4d3SLarry Finger 
110f1d2b4d3SLarry Finger 	do {
111f1d2b4d3SLarry Finger 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
112c93ac39dSLarry Finger 		if (value32 & WINTINI_RDY)
113c93ac39dSLarry Finger 			return 0;
114f1d2b4d3SLarry Finger 
115f1d2b4d3SLarry Finger 		udelay(FW_8192C_POLLING_DELAY*10);
116f1d2b4d3SLarry Finger 
117f1d2b4d3SLarry Finger 	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
118f1d2b4d3SLarry Finger 
119a44f59d6SLarry Finger 	pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
120f1d2b4d3SLarry Finger 	       value32, counter);
121f1d2b4d3SLarry Finger 
122f1d2b4d3SLarry Finger exit:
123f1d2b4d3SLarry Finger 	return err;
124f1d2b4d3SLarry Finger }
125f1d2b4d3SLarry Finger 
126f1d2b4d3SLarry Finger int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
127f1d2b4d3SLarry Finger {
128f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
129f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
130f1d2b4d3SLarry Finger 	struct rtlwifi_firmware_header *pfwheader;
131f1d2b4d3SLarry Finger 	u8 *pfwdata;
132f1d2b4d3SLarry Finger 	u32 fwsize;
133f1d2b4d3SLarry Finger 	int err;
134f1d2b4d3SLarry Finger 	enum version_8192e version = rtlhal->version;
135f1d2b4d3SLarry Finger 
136f1d2b4d3SLarry Finger 	if (!rtlhal->pfirmware)
137f1d2b4d3SLarry Finger 		return 1;
138f1d2b4d3SLarry Finger 
139f1d2b4d3SLarry Finger 	pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
140f1d2b4d3SLarry Finger 	rtlhal->fw_version = le16_to_cpu(pfwheader->version);
141f1d2b4d3SLarry Finger 	rtlhal->fw_subversion = pfwheader->subversion;
142f1d2b4d3SLarry Finger 	pfwdata = (u8 *)rtlhal->pfirmware;
143f1d2b4d3SLarry Finger 	fwsize = rtlhal->fwsize;
144f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
145f1d2b4d3SLarry Finger 		 "normal Firmware SIZE %d\n" , fwsize);
146f1d2b4d3SLarry Finger 
147f1d2b4d3SLarry Finger 	if (IS_FW_HEADER_EXIST(pfwheader)) {
148f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
149f1d2b4d3SLarry Finger 			 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
150f1d2b4d3SLarry Finger 			  pfwheader->version, pfwheader->signature,
151f1d2b4d3SLarry Finger 			  (int)sizeof(struct rtlwifi_firmware_header));
152f1d2b4d3SLarry Finger 
153f1d2b4d3SLarry Finger 		pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
154f1d2b4d3SLarry Finger 		fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
155f1d2b4d3SLarry Finger 	} else {
156f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
157f1d2b4d3SLarry Finger 			 "Firmware no Header, Signature(%#x)\n",
158f1d2b4d3SLarry Finger 			  pfwheader->signature);
159f1d2b4d3SLarry Finger 	}
160f1d2b4d3SLarry Finger 
161f1d2b4d3SLarry Finger 	if (rtlhal->mac_func_enable) {
162f1d2b4d3SLarry Finger 		if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
163f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
164f1d2b4d3SLarry Finger 			rtl92ee_firmware_selfreset(hw);
165f1d2b4d3SLarry Finger 		}
166f1d2b4d3SLarry Finger 	}
167f1d2b4d3SLarry Finger 	_rtl92ee_enable_fw_download(hw, true);
168f1d2b4d3SLarry Finger 	_rtl92ee_write_fw(hw, version, pfwdata, fwsize);
169f1d2b4d3SLarry Finger 	_rtl92ee_enable_fw_download(hw, false);
170f1d2b4d3SLarry Finger 
171f1d2b4d3SLarry Finger 	err = _rtl92ee_fw_free_to_go(hw);
172f1d2b4d3SLarry Finger 
173f1d2b4d3SLarry Finger 	return 0;
174f1d2b4d3SLarry Finger }
175f1d2b4d3SLarry Finger 
176f1d2b4d3SLarry Finger static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
177f1d2b4d3SLarry Finger {
178f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
179f1d2b4d3SLarry Finger 	u8 val_hmetfr;
180f1d2b4d3SLarry Finger 	bool result = false;
181f1d2b4d3SLarry Finger 
182f1d2b4d3SLarry Finger 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
183f1d2b4d3SLarry Finger 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
184f1d2b4d3SLarry Finger 		result = true;
185f1d2b4d3SLarry Finger 	return result;
186f1d2b4d3SLarry Finger }
187f1d2b4d3SLarry Finger 
188f1d2b4d3SLarry Finger static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
189f1d2b4d3SLarry Finger 				      u32 cmd_len, u8 *cmdbuffer)
190f1d2b4d3SLarry Finger {
191f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
192f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
193f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
194f1d2b4d3SLarry Finger 	u8 boxnum;
195f1d2b4d3SLarry Finger 	u16 box_reg = 0, box_extreg = 0;
196f1d2b4d3SLarry Finger 	u8 u1b_tmp;
197f1d2b4d3SLarry Finger 	bool isfw_read = false;
198f1d2b4d3SLarry Finger 	u8 buf_index = 0;
199f1d2b4d3SLarry Finger 	bool bwrite_sucess = false;
200f1d2b4d3SLarry Finger 	u8 wait_h2c_limmit = 100;
201f1d2b4d3SLarry Finger 	u8 boxcontent[4], boxextcontent[4];
202f1d2b4d3SLarry Finger 	u32 h2c_waitcounter = 0;
203f1d2b4d3SLarry Finger 	unsigned long flag;
204f1d2b4d3SLarry Finger 	u8 idx;
205f1d2b4d3SLarry Finger 
206f1d2b4d3SLarry Finger 	if (ppsc->dot11_psmode != EACTIVE ||
207f1d2b4d3SLarry Finger 	    ppsc->inactive_pwrstate == ERFOFF) {
208f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
209f1d2b4d3SLarry Finger 			 "FillH2CCommand8192E(): Return because RF is off!!!\n");
210f1d2b4d3SLarry Finger 		return;
211f1d2b4d3SLarry Finger 	}
212f1d2b4d3SLarry Finger 
213f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n");
214f1d2b4d3SLarry Finger 
215f1d2b4d3SLarry Finger 	/* 1. Prevent race condition in setting H2C cmd.
216f1d2b4d3SLarry Finger 	 * (copy from MgntActSet_RF_State().)
217f1d2b4d3SLarry Finger 	 */
218f1d2b4d3SLarry Finger 	while (true) {
219f1d2b4d3SLarry Finger 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
220f1d2b4d3SLarry Finger 		if (rtlhal->h2c_setinprogress) {
221f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
222f1d2b4d3SLarry Finger 				 "H2C set in progress! Wait to set..element_id(%d).\n",
223f1d2b4d3SLarry Finger 				  element_id);
224f1d2b4d3SLarry Finger 
225f1d2b4d3SLarry Finger 			while (rtlhal->h2c_setinprogress) {
226f1d2b4d3SLarry Finger 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
227f1d2b4d3SLarry Finger 						       flag);
228f1d2b4d3SLarry Finger 				h2c_waitcounter++;
229f1d2b4d3SLarry Finger 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
230f1d2b4d3SLarry Finger 					 "Wait 100 us (%d times)...\n",
231f1d2b4d3SLarry Finger 					  h2c_waitcounter);
232f1d2b4d3SLarry Finger 				udelay(100);
233f1d2b4d3SLarry Finger 
234f1d2b4d3SLarry Finger 				if (h2c_waitcounter > 1000)
235f1d2b4d3SLarry Finger 					return;
236f1d2b4d3SLarry Finger 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
237f1d2b4d3SLarry Finger 						  flag);
238f1d2b4d3SLarry Finger 			}
239f1d2b4d3SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
240f1d2b4d3SLarry Finger 		} else {
241f1d2b4d3SLarry Finger 			rtlhal->h2c_setinprogress = true;
242f1d2b4d3SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
243f1d2b4d3SLarry Finger 			break;
244f1d2b4d3SLarry Finger 		}
245f1d2b4d3SLarry Finger 	}
246f1d2b4d3SLarry Finger 
247f1d2b4d3SLarry Finger 	while (!bwrite_sucess) {
248f1d2b4d3SLarry Finger 		/* 2. Find the last BOX number which has been writen. */
249f1d2b4d3SLarry Finger 		boxnum = rtlhal->last_hmeboxnum;
250f1d2b4d3SLarry Finger 		switch (boxnum) {
251f1d2b4d3SLarry Finger 		case 0:
252f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_0;
253f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_0;
254f1d2b4d3SLarry Finger 			break;
255f1d2b4d3SLarry Finger 		case 1:
256f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_1;
257f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_1;
258f1d2b4d3SLarry Finger 			break;
259f1d2b4d3SLarry Finger 		case 2:
260f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_2;
261f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_2;
262f1d2b4d3SLarry Finger 			break;
263f1d2b4d3SLarry Finger 		case 3:
264f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_3;
265f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_3;
266f1d2b4d3SLarry Finger 			break;
267f1d2b4d3SLarry Finger 		default:
268f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
269ad574889SJoe Perches 				 "switch case %#x not processed\n", boxnum);
270f1d2b4d3SLarry Finger 			break;
271f1d2b4d3SLarry Finger 		}
272f1d2b4d3SLarry Finger 
273f1d2b4d3SLarry Finger 		/* 3. Check if the box content is empty. */
274f1d2b4d3SLarry Finger 		isfw_read = false;
275f1d2b4d3SLarry Finger 		u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
276f1d2b4d3SLarry Finger 
277f1d2b4d3SLarry Finger 		if (u1b_tmp != 0xea) {
278f1d2b4d3SLarry Finger 			isfw_read = true;
279f1d2b4d3SLarry Finger 		} else {
280f1d2b4d3SLarry Finger 			if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
281f1d2b4d3SLarry Finger 			    rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
282f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
283f1d2b4d3SLarry Finger 		}
284f1d2b4d3SLarry Finger 
285f1d2b4d3SLarry Finger 		if (isfw_read) {
286f1d2b4d3SLarry Finger 			wait_h2c_limmit = 100;
287f1d2b4d3SLarry Finger 			isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
288f1d2b4d3SLarry Finger 			while (!isfw_read) {
289f1d2b4d3SLarry Finger 				wait_h2c_limmit--;
290f1d2b4d3SLarry Finger 				if (wait_h2c_limmit == 0) {
291f1d2b4d3SLarry Finger 					RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
292f1d2b4d3SLarry Finger 						 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
293f1d2b4d3SLarry Finger 						 boxnum);
294f1d2b4d3SLarry Finger 					break;
295f1d2b4d3SLarry Finger 				}
296f1d2b4d3SLarry Finger 				udelay(10);
297f1d2b4d3SLarry Finger 				isfw_read =
298f1d2b4d3SLarry Finger 				  _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
299f1d2b4d3SLarry Finger 				u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
300f1d2b4d3SLarry Finger 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
301f1d2b4d3SLarry Finger 					 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
302f1d2b4d3SLarry Finger 					 boxnum, u1b_tmp);
303f1d2b4d3SLarry Finger 			}
304f1d2b4d3SLarry Finger 		}
305f1d2b4d3SLarry Finger 
306f1d2b4d3SLarry Finger 		/* If Fw has not read the last
307f1d2b4d3SLarry Finger 		 * H2C cmd, break and give up this H2C.
308f1d2b4d3SLarry Finger 		 */
309f1d2b4d3SLarry Finger 		if (!isfw_read) {
310f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
311f1d2b4d3SLarry Finger 				 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
312f1d2b4d3SLarry Finger 				 boxnum);
313f1d2b4d3SLarry Finger 			break;
314f1d2b4d3SLarry Finger 		}
315f1d2b4d3SLarry Finger 		/* 4. Fill the H2C cmd into box */
316f1d2b4d3SLarry Finger 		memset(boxcontent, 0, sizeof(boxcontent));
317f1d2b4d3SLarry Finger 		memset(boxextcontent, 0, sizeof(boxextcontent));
318f1d2b4d3SLarry Finger 		boxcontent[0] = element_id;
319f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
320f1d2b4d3SLarry Finger 			 "Write element_id box_reg(%4x) = %2x\n",
321f1d2b4d3SLarry Finger 			  box_reg, element_id);
322f1d2b4d3SLarry Finger 
323f1d2b4d3SLarry Finger 		switch (cmd_len) {
324f1d2b4d3SLarry Finger 		case 1:
325f1d2b4d3SLarry Finger 		case 2:
326f1d2b4d3SLarry Finger 		case 3:
327f1d2b4d3SLarry Finger 			/*boxcontent[0] &= ~(BIT(7));*/
328f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
329f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index, cmd_len);
330f1d2b4d3SLarry Finger 
331f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
332f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
333f1d2b4d3SLarry Finger 					       boxcontent[idx]);
334f1d2b4d3SLarry Finger 			}
335f1d2b4d3SLarry Finger 			break;
336f1d2b4d3SLarry Finger 		case 4:
337f1d2b4d3SLarry Finger 		case 5:
338f1d2b4d3SLarry Finger 		case 6:
339f1d2b4d3SLarry Finger 		case 7:
340f1d2b4d3SLarry Finger 			/*boxcontent[0] |= (BIT(7));*/
341f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxextcontent),
342f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index+3, cmd_len-3);
343f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
344f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index, 3);
345f1d2b4d3SLarry Finger 
346f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
347f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_extreg + idx,
348f1d2b4d3SLarry Finger 					       boxextcontent[idx]);
349f1d2b4d3SLarry Finger 			}
350f1d2b4d3SLarry Finger 
351f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
352f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
353f1d2b4d3SLarry Finger 					       boxcontent[idx]);
354f1d2b4d3SLarry Finger 			}
355f1d2b4d3SLarry Finger 			break;
356f1d2b4d3SLarry Finger 		default:
357f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
358ad574889SJoe Perches 				 "switch case %#x not processed\n", cmd_len);
359f1d2b4d3SLarry Finger 			break;
360f1d2b4d3SLarry Finger 		}
361f1d2b4d3SLarry Finger 
362f1d2b4d3SLarry Finger 		bwrite_sucess = true;
363f1d2b4d3SLarry Finger 
364f1d2b4d3SLarry Finger 		rtlhal->last_hmeboxnum = boxnum + 1;
365f1d2b4d3SLarry Finger 		if (rtlhal->last_hmeboxnum == 4)
366f1d2b4d3SLarry Finger 			rtlhal->last_hmeboxnum = 0;
367f1d2b4d3SLarry Finger 
368f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
369f1d2b4d3SLarry Finger 			 "pHalData->last_hmeboxnum  = %d\n",
370f1d2b4d3SLarry Finger 			  rtlhal->last_hmeboxnum);
371f1d2b4d3SLarry Finger 	}
372f1d2b4d3SLarry Finger 
373f1d2b4d3SLarry Finger 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
374f1d2b4d3SLarry Finger 	rtlhal->h2c_setinprogress = false;
375f1d2b4d3SLarry Finger 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
376f1d2b4d3SLarry Finger 
377f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n");
378f1d2b4d3SLarry Finger }
379f1d2b4d3SLarry Finger 
380f1d2b4d3SLarry Finger void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
381f1d2b4d3SLarry Finger 			  u8 element_id, u32 cmd_len, u8 *cmdbuffer)
382f1d2b4d3SLarry Finger {
383f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
384f1d2b4d3SLarry Finger 	u32 tmp_cmdbuf[2];
385f1d2b4d3SLarry Finger 
386f1d2b4d3SLarry Finger 	if (!rtlhal->fw_ready) {
387531940f9SLarry Finger 		WARN_ONCE(true,
388531940f9SLarry Finger 			  "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
389f1d2b4d3SLarry Finger 		return;
390f1d2b4d3SLarry Finger 	}
391f1d2b4d3SLarry Finger 
392f1d2b4d3SLarry Finger 	memset(tmp_cmdbuf, 0, 8);
393f1d2b4d3SLarry Finger 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
394f1d2b4d3SLarry Finger 	_rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
395f1d2b4d3SLarry Finger }
396f1d2b4d3SLarry Finger 
397f1d2b4d3SLarry Finger void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
398f1d2b4d3SLarry Finger {
399f1d2b4d3SLarry Finger 	u8 u1b_tmp;
400f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
401f1d2b4d3SLarry Finger 
402f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
403f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
404f1d2b4d3SLarry Finger 
405f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
406f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
407f1d2b4d3SLarry Finger 
408f1d2b4d3SLarry Finger 	udelay(50);
409f1d2b4d3SLarry Finger 
410f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
411f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
412f1d2b4d3SLarry Finger 
413f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
414f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
415f1d2b4d3SLarry Finger 
416f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD ,
417f1d2b4d3SLarry Finger 		 "  _8051Reset92E(): 8051 reset success .\n");
418f1d2b4d3SLarry Finger }
419f1d2b4d3SLarry Finger 
420f1d2b4d3SLarry Finger void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
421f1d2b4d3SLarry Finger {
422f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
423f1d2b4d3SLarry Finger 	u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
424f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
42542213f2fSPing-Ke Shih 	u8 rlbm, power_state = 0, byte5 = 0;
42642213f2fSPing-Ke Shih 	u8 awake_intvl;	/* DTIM = (awake_intvl - 1) */
42754685f9cSPing-Ke Shih 	struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
42842213f2fSPing-Ke Shih 	bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
42942213f2fSPing-Ke Shih 			    btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
430135f4fbdSPing-Ke Shih 	bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
431135f4fbdSPing-Ke Shih 			  btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
432135f4fbdSPing-Ke Shih 
433135f4fbdSPing-Ke Shih 	if (bt_ctrl_lps)
434135f4fbdSPing-Ke Shih 		mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
435f1d2b4d3SLarry Finger 
43642213f2fSPing-Ke Shih 	RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
43742213f2fSPing-Ke Shih 		 mode, bt_ctrl_lps);
43842213f2fSPing-Ke Shih 
43942213f2fSPing-Ke Shih 	switch (mode) {
44042213f2fSPing-Ke Shih 	case FW_PS_MIN_MODE:
44142213f2fSPing-Ke Shih 		rlbm = 0;
44242213f2fSPing-Ke Shih 		awake_intvl = 2;
44342213f2fSPing-Ke Shih 		break;
44442213f2fSPing-Ke Shih 	case FW_PS_MAX_MODE:
44542213f2fSPing-Ke Shih 		rlbm = 1;
44642213f2fSPing-Ke Shih 		awake_intvl = 2;
44742213f2fSPing-Ke Shih 		break;
44842213f2fSPing-Ke Shih 	case FW_PS_DTIM_MODE:
44942213f2fSPing-Ke Shih 		rlbm = 2;
45042213f2fSPing-Ke Shih 		awake_intvl = ppsc->reg_max_lps_awakeintvl;
45142213f2fSPing-Ke Shih 		/* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
45242213f2fSPing-Ke Shih 		 * is only used in swlps.
45342213f2fSPing-Ke Shih 		 */
45442213f2fSPing-Ke Shih 		break;
45542213f2fSPing-Ke Shih 	default:
45642213f2fSPing-Ke Shih 		rlbm = 2;
45742213f2fSPing-Ke Shih 		awake_intvl = 4;
45842213f2fSPing-Ke Shih 		break;
45942213f2fSPing-Ke Shih 	}
46042213f2fSPing-Ke Shih 
46142213f2fSPing-Ke Shih 	if (rtlpriv->mac80211.p2p) {
46242213f2fSPing-Ke Shih 		awake_intvl = 2;
46342213f2fSPing-Ke Shih 		rlbm = 1;
46442213f2fSPing-Ke Shih 	}
46542213f2fSPing-Ke Shih 
46642213f2fSPing-Ke Shih 	if (mode == FW_PS_ACTIVE_MODE) {
46742213f2fSPing-Ke Shih 		byte5 = 0x40;
46842213f2fSPing-Ke Shih 		power_state = FW_PWR_STATE_ACTIVE;
46942213f2fSPing-Ke Shih 	} else {
47042213f2fSPing-Ke Shih 		if (bt_ctrl_lps) {
47142213f2fSPing-Ke Shih 			byte5 = btc_ops->btc_get_lps_val(rtlpriv);
47242213f2fSPing-Ke Shih 			power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
47342213f2fSPing-Ke Shih 
47442213f2fSPing-Ke Shih 			if ((rlbm == 2) && (byte5 & BIT(4))) {
47542213f2fSPing-Ke Shih 				/* Keep awake interval to 1 to prevent from
47642213f2fSPing-Ke Shih 				 * decreasing coex performance
47742213f2fSPing-Ke Shih 				 */
47842213f2fSPing-Ke Shih 				awake_intvl = 2;
47942213f2fSPing-Ke Shih 				rlbm = 2;
48042213f2fSPing-Ke Shih 			}
48142213f2fSPing-Ke Shih 		} else {
48242213f2fSPing-Ke Shih 			byte5 = 0x40;
48342213f2fSPing-Ke Shih 			power_state = FW_PWR_STATE_RF_OFF;
48442213f2fSPing-Ke Shih 		}
48542213f2fSPing-Ke Shih 	}
486f1d2b4d3SLarry Finger 
487f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
488f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
489f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
490135f4fbdSPing-Ke Shih 					 bt_ctrl_lps ? 0 :
491135f4fbdSPing-Ke Shih 					 ((rtlpriv->mac80211.p2p) ?
492135f4fbdSPing-Ke Shih 					  ppsc->smart_ps : 1));
493f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
49442213f2fSPing-Ke Shih 					       awake_intvl);
495f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
496f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
49754685f9cSPing-Ke Shih 	SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
498f1d2b4d3SLarry Finger 
499f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
500f1d2b4d3SLarry Finger 		      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
501f1d2b4d3SLarry Finger 		      u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
50254685f9cSPing-Ke Shih 	if (rtlpriv->cfg->ops->get_btc_status())
50354685f9cSPing-Ke Shih 		btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
50454685f9cSPing-Ke Shih 					     H2C_92E_PWEMODE_LENGTH);
505f1d2b4d3SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
506f1d2b4d3SLarry Finger 			     u1_h2c_set_pwrmode);
507f1d2b4d3SLarry Finger }
508f1d2b4d3SLarry Finger 
509f1d2b4d3SLarry Finger void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
510f1d2b4d3SLarry Finger {
511f1d2b4d3SLarry Finger 	u8 parm[3] = { 0 , 0 , 0 };
512f1d2b4d3SLarry Finger 	/* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
513f1d2b4d3SLarry Finger 	 *          bit1=0-->update Media Status to MACID
514f1d2b4d3SLarry Finger 	 *          bit1=1-->update Media Status from MACID to MACID_End
515f1d2b4d3SLarry Finger 	 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
516f1d2b4d3SLarry Finger 	 * parm[2]: MACID_End
517f1d2b4d3SLarry Finger 	 */
518f1d2b4d3SLarry Finger 
519f1d2b4d3SLarry Finger 	SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
520f1d2b4d3SLarry Finger 	SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
521f1d2b4d3SLarry Finger 
522f1d2b4d3SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
523f1d2b4d3SLarry Finger }
524f1d2b4d3SLarry Finger 
525f1d2b4d3SLarry Finger #define BEACON_PG		0 /* ->1 */
526f1d2b4d3SLarry Finger #define PSPOLL_PG		2
527f1d2b4d3SLarry Finger #define NULL_PG			3
528f1d2b4d3SLarry Finger #define PROBERSP_PG		4 /* ->5 */
52974a7dfbcSPing-Ke Shih #define QOS_NULL_PG		6
53074a7dfbcSPing-Ke Shih #define BT_QOS_NULL_PG	7
531f1d2b4d3SLarry Finger 
53274a7dfbcSPing-Ke Shih #define TOTAL_RESERVED_PKT_LEN	1024
533f1d2b4d3SLarry Finger 
534f1d2b4d3SLarry Finger static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
535f1d2b4d3SLarry Finger 	/* page 0 beacon */
536f1d2b4d3SLarry Finger 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
537f1d2b4d3SLarry Finger 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
538f1d2b4d3SLarry Finger 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
539f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540f1d2b4d3SLarry Finger 	0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
541f1d2b4d3SLarry Finger 	0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
542f1d2b4d3SLarry Finger 	0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
543f1d2b4d3SLarry Finger 	0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
544f1d2b4d3SLarry Finger 	0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
545f1d2b4d3SLarry Finger 	0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
546f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548f1d2b4d3SLarry Finger 	0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
549f1d2b4d3SLarry Finger 	0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
550f1d2b4d3SLarry Finger 	0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
551f1d2b4d3SLarry Finger 	0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
552f1d2b4d3SLarry Finger 
553f1d2b4d3SLarry Finger 	/* page 1 beacon */
554f1d2b4d3SLarry Finger 	0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
555f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565f1d2b4d3SLarry Finger 	0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
566f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
567f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570f1d2b4d3SLarry Finger 
571f1d2b4d3SLarry Finger 	/* page 2  ps-poll */
572f1d2b4d3SLarry Finger 	0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
573f1d2b4d3SLarry Finger 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
574f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583f1d2b4d3SLarry Finger 	0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
584f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
585f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587f1d2b4d3SLarry Finger 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588f1d2b4d3SLarry Finger 
589f1d2b4d3SLarry Finger 	/* page 3  null */
590f1d2b4d3SLarry Finger 	0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
591f1d2b4d3SLarry Finger 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
592f1d2b4d3SLarry Finger 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
593f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601f1d2b4d3SLarry Finger 	0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
602f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
603f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605f1d2b4d3SLarry Finger 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606f1d2b4d3SLarry Finger 
607f1d2b4d3SLarry Finger 	/* page 4  probe_resp */
608f1d2b4d3SLarry Finger 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
609f1d2b4d3SLarry Finger 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
610f1d2b4d3SLarry Finger 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
611f1d2b4d3SLarry Finger 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
612f1d2b4d3SLarry Finger 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
613f1d2b4d3SLarry Finger 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
614f1d2b4d3SLarry Finger 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
615f1d2b4d3SLarry Finger 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
616f1d2b4d3SLarry Finger 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
617f1d2b4d3SLarry Finger 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
618f1d2b4d3SLarry Finger 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621f1d2b4d3SLarry Finger 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
622f1d2b4d3SLarry Finger 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624f1d2b4d3SLarry Finger 
625f1d2b4d3SLarry Finger 	/* page 5  probe_resp */
626f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63374a7dfbcSPing-Ke Shih 	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
63474a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
63574a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63674a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63774a7dfbcSPing-Ke Shih 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63874a7dfbcSPing-Ke Shih 
63974a7dfbcSPing-Ke Shih 	/* page 6 qos null data */
64074a7dfbcSPing-Ke Shih 	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
64174a7dfbcSPing-Ke Shih 	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
64274a7dfbcSPing-Ke Shih 	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
64374a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64474a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64574a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64674a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64774a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64874a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64974a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65074a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65174a7dfbcSPing-Ke Shih 	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
65274a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
65374a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65474a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65574a7dfbcSPing-Ke Shih 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65674a7dfbcSPing-Ke Shih 
65774a7dfbcSPing-Ke Shih 	/* page 7 BT-qos null data */
65874a7dfbcSPing-Ke Shih 	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
65974a7dfbcSPing-Ke Shih 	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
66074a7dfbcSPing-Ke Shih 	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
66174a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66274a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66374a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66474a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66574a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66674a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66774a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66874a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678f1d2b4d3SLarry Finger };
679f1d2b4d3SLarry Finger 
680f1d2b4d3SLarry Finger void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
681f1d2b4d3SLarry Finger {
682f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
683f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
684f1d2b4d3SLarry Finger 	struct sk_buff *skb = NULL;
685519ce2f9SLarry Finger 	bool rtstatus;
686f1d2b4d3SLarry Finger 	u32 totalpacketlen;
687f1d2b4d3SLarry Finger 	u8 u1rsvdpageloc[5] = { 0 };
688f1d2b4d3SLarry Finger 	bool b_dlok = false;
689f1d2b4d3SLarry Finger 
690f1d2b4d3SLarry Finger 	u8 *beacon;
691f1d2b4d3SLarry Finger 	u8 *p_pspoll;
692f1d2b4d3SLarry Finger 	u8 *nullfunc;
693f1d2b4d3SLarry Finger 	u8 *p_probersp;
69474a7dfbcSPing-Ke Shih 	u8 *qosnull;
69574a7dfbcSPing-Ke Shih 	u8 *btqosnull;
696f1d2b4d3SLarry Finger 	/*---------------------------------------------------------
697f1d2b4d3SLarry Finger 	 *			(1) beacon
698f1d2b4d3SLarry Finger 	 *---------------------------------------------------------
699f1d2b4d3SLarry Finger 	 */
700f1d2b4d3SLarry Finger 	beacon = &reserved_page_packet[BEACON_PG * 128];
701f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
702f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
703f1d2b4d3SLarry Finger 
704f1d2b4d3SLarry Finger 	/*-------------------------------------------------------
705f1d2b4d3SLarry Finger 	 *			(2) ps-poll
706f1d2b4d3SLarry Finger 	 *--------------------------------------------------------
707f1d2b4d3SLarry Finger 	 */
708f1d2b4d3SLarry Finger 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
709f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
710f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
711f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
712f1d2b4d3SLarry Finger 
713f1d2b4d3SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
714f1d2b4d3SLarry Finger 
715f1d2b4d3SLarry Finger 	/*--------------------------------------------------------
716f1d2b4d3SLarry Finger 	 *			(3) null data
717f1d2b4d3SLarry Finger 	 *---------------------------------------------------------
718f1d2b4d3SLarry Finger 	 */
719f1d2b4d3SLarry Finger 	nullfunc = &reserved_page_packet[NULL_PG * 128];
720f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
721f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
722f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
723f1d2b4d3SLarry Finger 
724f1d2b4d3SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
725f1d2b4d3SLarry Finger 
726f1d2b4d3SLarry Finger 	/*---------------------------------------------------------
727f1d2b4d3SLarry Finger 	 *			(4) probe response
728f1d2b4d3SLarry Finger 	 *----------------------------------------------------------
729f1d2b4d3SLarry Finger 	 */
730f1d2b4d3SLarry Finger 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
731f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
732f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
733f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
734f1d2b4d3SLarry Finger 
735f1d2b4d3SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
736f1d2b4d3SLarry Finger 
73774a7dfbcSPing-Ke Shih 	/*---------------------------------------------------------
73874a7dfbcSPing-Ke Shih 	 *			(5) QoS null data
73974a7dfbcSPing-Ke Shih 	 *----------------------------------------------------------
74074a7dfbcSPing-Ke Shih 	 */
74174a7dfbcSPing-Ke Shih 	qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
74274a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
74374a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
74474a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
74574a7dfbcSPing-Ke Shih 
74674a7dfbcSPing-Ke Shih 	SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
74774a7dfbcSPing-Ke Shih 
74874a7dfbcSPing-Ke Shih 	/*---------------------------------------------------------
74974a7dfbcSPing-Ke Shih 	 *			(6) BT QoS null data
75074a7dfbcSPing-Ke Shih 	 *----------------------------------------------------------
75174a7dfbcSPing-Ke Shih 	 */
75274a7dfbcSPing-Ke Shih 	btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
75374a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
75474a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
75574a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
75674a7dfbcSPing-Ke Shih 
75774a7dfbcSPing-Ke Shih 	SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
75874a7dfbcSPing-Ke Shih 
759f1d2b4d3SLarry Finger 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
760f1d2b4d3SLarry Finger 
761f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
762f1d2b4d3SLarry Finger 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
763f1d2b4d3SLarry Finger 		      &reserved_page_packet[0], totalpacketlen);
764f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
765f1d2b4d3SLarry Finger 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
766f1d2b4d3SLarry Finger 		      u1rsvdpageloc, 3);
767f1d2b4d3SLarry Finger 
768f1d2b4d3SLarry Finger 	skb = dev_alloc_skb(totalpacketlen);
769ad941e69Syuan linyu 	skb_put_data(skb, &reserved_page_packet, totalpacketlen);
770f1d2b4d3SLarry Finger 
771519ce2f9SLarry Finger 	rtstatus = rtl_cmd_send_packet(hw, skb);
772519ce2f9SLarry Finger 	if (rtstatus)
773f1d2b4d3SLarry Finger 		b_dlok = true;
774f1d2b4d3SLarry Finger 
775f1d2b4d3SLarry Finger 	if (b_dlok) {
776f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
777f1d2b4d3SLarry Finger 			 "Set RSVD page location to Fw.\n");
778f1d2b4d3SLarry Finger 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
779f1d2b4d3SLarry Finger 			      "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
780f1d2b4d3SLarry Finger 		rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
781f1d2b4d3SLarry Finger 				     sizeof(u1rsvdpageloc), u1rsvdpageloc);
782f1d2b4d3SLarry Finger 	} else {
783f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
784f1d2b4d3SLarry Finger 			 "Set RSVD page location to Fw FAIL!!!!!!.\n");
785f1d2b4d3SLarry Finger 	}
786f1d2b4d3SLarry Finger }
787f1d2b4d3SLarry Finger 
788f1d2b4d3SLarry Finger /*Shoud check FW support p2p or not.*/
789f1d2b4d3SLarry Finger static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
790f1d2b4d3SLarry Finger {
791f1d2b4d3SLarry Finger 	u8 u1_ctwindow_period[1] = {ctwindow};
792f1d2b4d3SLarry Finger 
793f1d2b4d3SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
794f1d2b4d3SLarry Finger }
795f1d2b4d3SLarry Finger 
796f1d2b4d3SLarry Finger void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
797f1d2b4d3SLarry Finger {
798f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
799f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
800f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
801f1d2b4d3SLarry Finger 	struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
802f1d2b4d3SLarry Finger 	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
803f1d2b4d3SLarry Finger 	u8 i;
804f1d2b4d3SLarry Finger 	u16 ctwindow;
805f1d2b4d3SLarry Finger 	u32 start_time, tsf_low;
806f1d2b4d3SLarry Finger 
807f1d2b4d3SLarry Finger 	switch (p2p_ps_state) {
808f1d2b4d3SLarry Finger 	case P2P_PS_DISABLE:
809f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
810f1d2b4d3SLarry Finger 		memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
811f1d2b4d3SLarry Finger 		break;
812f1d2b4d3SLarry Finger 	case P2P_PS_ENABLE:
813f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
814f1d2b4d3SLarry Finger 		/* update CTWindow value. */
815f1d2b4d3SLarry Finger 		if (p2pinfo->ctwindow > 0) {
816f1d2b4d3SLarry Finger 			p2p_ps_offload->ctwindow_en = 1;
817f1d2b4d3SLarry Finger 			ctwindow = p2pinfo->ctwindow;
818f1d2b4d3SLarry Finger 			rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
819f1d2b4d3SLarry Finger 		}
820f1d2b4d3SLarry Finger 		/* hw only support 2 set of NoA */
821f1d2b4d3SLarry Finger 		for (i = 0 ; i < p2pinfo->noa_num ; i++) {
822f1d2b4d3SLarry Finger 			/* To control the register setting for which NOA*/
823f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
824f1d2b4d3SLarry Finger 			if (i == 0)
825f1d2b4d3SLarry Finger 				p2p_ps_offload->noa0_en = 1;
826f1d2b4d3SLarry Finger 			else
827f1d2b4d3SLarry Finger 				p2p_ps_offload->noa1_en = 1;
828f1d2b4d3SLarry Finger 			/* config P2P NoA Descriptor Register */
829f1d2b4d3SLarry Finger 			rtl_write_dword(rtlpriv, 0x5E0,
830f1d2b4d3SLarry Finger 					p2pinfo->noa_duration[i]);
831f1d2b4d3SLarry Finger 			rtl_write_dword(rtlpriv, 0x5E4,
832f1d2b4d3SLarry Finger 					p2pinfo->noa_interval[i]);
833f1d2b4d3SLarry Finger 
834f1d2b4d3SLarry Finger 			/*Get Current TSF value */
835f1d2b4d3SLarry Finger 			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
836f1d2b4d3SLarry Finger 
837f1d2b4d3SLarry Finger 			start_time = p2pinfo->noa_start_time[i];
838f1d2b4d3SLarry Finger 			if (p2pinfo->noa_count_type[i] != 1) {
839f1d2b4d3SLarry Finger 				while (start_time <= (tsf_low + (50 * 1024))) {
840f1d2b4d3SLarry Finger 					start_time += p2pinfo->noa_interval[i];
841f1d2b4d3SLarry Finger 					if (p2pinfo->noa_count_type[i] != 255)
842f1d2b4d3SLarry Finger 						p2pinfo->noa_count_type[i]--;
843f1d2b4d3SLarry Finger 				}
844f1d2b4d3SLarry Finger 			}
845f1d2b4d3SLarry Finger 			rtl_write_dword(rtlpriv, 0x5E8, start_time);
846f1d2b4d3SLarry Finger 			rtl_write_dword(rtlpriv, 0x5EC,
847f1d2b4d3SLarry Finger 					p2pinfo->noa_count_type[i]);
848f1d2b4d3SLarry Finger 		}
849f1d2b4d3SLarry Finger 		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
850f1d2b4d3SLarry Finger 			/* rst p2p circuit */
851f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
852f1d2b4d3SLarry Finger 			p2p_ps_offload->offload_en = 1;
853f1d2b4d3SLarry Finger 
854f1d2b4d3SLarry Finger 			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
855f1d2b4d3SLarry Finger 				p2p_ps_offload->role = 1;
856f1d2b4d3SLarry Finger 				p2p_ps_offload->allstasleep = 0;
857f1d2b4d3SLarry Finger 			} else {
858f1d2b4d3SLarry Finger 				p2p_ps_offload->role = 0;
859f1d2b4d3SLarry Finger 			}
860f1d2b4d3SLarry Finger 			p2p_ps_offload->discovery = 0;
861f1d2b4d3SLarry Finger 		}
862f1d2b4d3SLarry Finger 		break;
863f1d2b4d3SLarry Finger 	case P2P_PS_SCAN:
864f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
865f1d2b4d3SLarry Finger 		p2p_ps_offload->discovery = 1;
866f1d2b4d3SLarry Finger 		break;
867f1d2b4d3SLarry Finger 	case P2P_PS_SCAN_DONE:
868f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
869f1d2b4d3SLarry Finger 		p2p_ps_offload->discovery = 0;
870f1d2b4d3SLarry Finger 		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
871f1d2b4d3SLarry Finger 		break;
872f1d2b4d3SLarry Finger 	default:
873f1d2b4d3SLarry Finger 		break;
874f1d2b4d3SLarry Finger 	}
875f1d2b4d3SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
876f1d2b4d3SLarry Finger 			     (u8 *)p2p_ps_offload);
877f1d2b4d3SLarry Finger }
878f1d2b4d3SLarry Finger 
879*16cefa44SPing-Ke Shih void rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
880f1d2b4d3SLarry Finger 				   u8 *cmd_buf, u8 cmd_len)
881f1d2b4d3SLarry Finger {
882f1d2b4d3SLarry Finger 	u8 rate = cmd_buf[0] & 0x3F;
883f1d2b4d3SLarry Finger 	bool collision_state = cmd_buf[3] & BIT(0);
884f1d2b4d3SLarry Finger 
885f1d2b4d3SLarry Finger 	rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
886f1d2b4d3SLarry Finger }
887f1d2b4d3SLarry Finger 
888cceb0a59SPing-Ke Shih void rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
889f1d2b4d3SLarry Finger 				 u8 c2h_cmd_len, u8 *tmp_buf)
890f1d2b4d3SLarry Finger {
891f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
892*16cefa44SPing-Ke Shih 	struct rtl_hal_ops *hal_ops = rtlpriv->cfg->ops;
8936aad6075SPing-Ke Shih 	struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
894f1d2b4d3SLarry Finger 
895f1d2b4d3SLarry Finger 	switch (c2h_cmd_id) {
8967aeb100bSPing-Ke Shih 	case C2H_DBG:
897f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
898f1d2b4d3SLarry Finger 			 "[C2H], C2H_8723BE_DBG!!\n");
899f1d2b4d3SLarry Finger 		break;
9007aeb100bSPing-Ke Shih 	case C2H_TXBF:
901f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
902f1d2b4d3SLarry Finger 			 "[C2H], C2H_8192E_TXBF!!\n");
903f1d2b4d3SLarry Finger 		break;
9047aeb100bSPing-Ke Shih 	case C2H_TX_REPORT:
905f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
906f1d2b4d3SLarry Finger 			 "[C2H], C2H_8723BE_TX_REPORT!\n");
9078479580bSPing-Ke Shih 		rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len);
908f1d2b4d3SLarry Finger 		break;
9097aeb100bSPing-Ke Shih 	case C2H_BT_INFO:
910f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
911f1d2b4d3SLarry Finger 			 "[C2H], C2H_8723BE_BT_INFO!!\n");
9126aad6075SPing-Ke Shih 		if (rtlpriv->cfg->ops->get_btc_status())
9136aad6075SPing-Ke Shih 			btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
914f1d2b4d3SLarry Finger 						   c2h_cmd_len);
915f1d2b4d3SLarry Finger 		break;
9167aeb100bSPing-Ke Shih 	case C2H_BT_MP:
917f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
918f1d2b4d3SLarry Finger 			 "[C2H], C2H_8723BE_BT_MP!!\n");
9196aad6075SPing-Ke Shih 		if (rtlpriv->cfg->ops->get_btc_status())
9206aad6075SPing-Ke Shih 			btc_ops->btc_btmpinfo_notify(rtlpriv, tmp_buf,
9216aad6075SPing-Ke Shih 						     c2h_cmd_len);
922f1d2b4d3SLarry Finger 		break;
9237aeb100bSPing-Ke Shih 	case C2H_RA_RPT:
924*16cefa44SPing-Ke Shih 		hal_ops->c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
925f1d2b4d3SLarry Finger 		break;
926f1d2b4d3SLarry Finger 	default:
927f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
928f1d2b4d3SLarry Finger 			 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
929f1d2b4d3SLarry Finger 		break;
930f1d2b4d3SLarry Finger 	}
931f1d2b4d3SLarry Finger }
932f1d2b4d3SLarry Finger 
933f1d2b4d3SLarry Finger void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
934f1d2b4d3SLarry Finger {
935f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
936f1d2b4d3SLarry Finger 	u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
937f1d2b4d3SLarry Finger 	u8 *tmp_buf = NULL;
938f1d2b4d3SLarry Finger 
939f1d2b4d3SLarry Finger 	c2h_cmd_id = buffer[0];
940f1d2b4d3SLarry Finger 	c2h_cmd_seq = buffer[1];
941f1d2b4d3SLarry Finger 	c2h_cmd_len = len - 2;
942f1d2b4d3SLarry Finger 	tmp_buf = buffer + 2;
943f1d2b4d3SLarry Finger 
944f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
945f1d2b4d3SLarry Finger 		 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
946f1d2b4d3SLarry Finger 		 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
947f1d2b4d3SLarry Finger 
948f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
949f1d2b4d3SLarry Finger 		      "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
950f1d2b4d3SLarry Finger 
951cceb0a59SPing-Ke Shih 	switch (c2h_cmd_id) {
9527aeb100bSPing-Ke Shih 	case C2H_BT_INFO:
9537aeb100bSPing-Ke Shih 	case C2H_BT_MP:
954cceb0a59SPing-Ke Shih 		rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
955cceb0a59SPing-Ke Shih 		break;
956cceb0a59SPing-Ke Shih 	default:
957cceb0a59SPing-Ke Shih 		rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
958cceb0a59SPing-Ke Shih 					    tmp_buf);
959cceb0a59SPing-Ke Shih 		break;
960cceb0a59SPing-Ke Shih 	}
961f1d2b4d3SLarry Finger }
962