xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
1647f21b1SLarry Finger // SPDX-License-Identifier: GPL-2.0
2647f21b1SLarry Finger /* Copyright(c) 2009-2014  Realtek Corporation.*/
3b1a3bfc9SLarry Finger 
4b1a3bfc9SLarry Finger #include "../wifi.h"
5b1a3bfc9SLarry Finger #include "../pci.h"
6b1a3bfc9SLarry Finger #include "../base.h"
7557f9331SLarry Finger #include "../core.h"
889d32c90SLarry Finger #include "../efuse.h"
9b1a3bfc9SLarry Finger #include "reg.h"
10b1a3bfc9SLarry Finger #include "def.h"
11b1a3bfc9SLarry Finger #include "fw.h"
12b1a3bfc9SLarry Finger #include "dm.h"
13b1a3bfc9SLarry Finger 
_rtl92ee_enable_fw_download(struct ieee80211_hw * hw,bool enable)14b1a3bfc9SLarry Finger static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
15b1a3bfc9SLarry Finger {
16b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
17b1a3bfc9SLarry Finger 	u8 tmp;
18b1a3bfc9SLarry Finger 
19b1a3bfc9SLarry Finger 	if (enable) {
20b1a3bfc9SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
21b1a3bfc9SLarry Finger 
22b1a3bfc9SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
23b1a3bfc9SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
24b1a3bfc9SLarry Finger 	} else {
25b1a3bfc9SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
26b1a3bfc9SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
27b1a3bfc9SLarry Finger 	}
28b1a3bfc9SLarry Finger }
29b1a3bfc9SLarry Finger 
_rtl92ee_write_fw(struct ieee80211_hw * hw,enum version_8192e version,u8 * buffer,u32 size)30b1a3bfc9SLarry Finger static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
31b1a3bfc9SLarry Finger 			      enum version_8192e version,
32b1a3bfc9SLarry Finger 			      u8 *buffer, u32 size)
33b1a3bfc9SLarry Finger {
34b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
35b1a3bfc9SLarry Finger 	u8 *bufferptr = (u8 *)buffer;
36b1a3bfc9SLarry Finger 	u32 pagenums, remainsize;
37b1a3bfc9SLarry Finger 	u32 page, offset;
38b1a3bfc9SLarry Finger 
39e24a2a87SLarry Finger 	rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
40b1a3bfc9SLarry Finger 
4189d32c90SLarry Finger 	rtl_fill_dummy(bufferptr, &size);
42b1a3bfc9SLarry Finger 
43b1a3bfc9SLarry Finger 	pagenums = size / FW_8192C_PAGE_SIZE;
44b1a3bfc9SLarry Finger 	remainsize = size % FW_8192C_PAGE_SIZE;
45b1a3bfc9SLarry Finger 
46a44f59d6SLarry Finger 	if (pagenums > 8)
47a44f59d6SLarry Finger 		pr_err("Page numbers should not greater then 8\n");
48b1a3bfc9SLarry Finger 
49b1a3bfc9SLarry Finger 	for (page = 0; page < pagenums; page++) {
50b1a3bfc9SLarry Finger 		offset = page * FW_8192C_PAGE_SIZE;
5189d32c90SLarry Finger 		rtl_fw_page_write(hw, page, (bufferptr + offset),
52b1a3bfc9SLarry Finger 				  FW_8192C_PAGE_SIZE);
53b1a3bfc9SLarry Finger 		udelay(2);
54b1a3bfc9SLarry Finger 	}
55b1a3bfc9SLarry Finger 
56b1a3bfc9SLarry Finger 	if (remainsize) {
57b1a3bfc9SLarry Finger 		offset = pagenums * FW_8192C_PAGE_SIZE;
58b1a3bfc9SLarry Finger 		page = pagenums;
5989d32c90SLarry Finger 		rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
60b1a3bfc9SLarry Finger 	}
61b1a3bfc9SLarry Finger }
62b1a3bfc9SLarry Finger 
_rtl92ee_fw_free_to_go(struct ieee80211_hw * hw)63b1a3bfc9SLarry Finger static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
64b1a3bfc9SLarry Finger {
65b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
66b1a3bfc9SLarry Finger 	int err = -EIO;
67b1a3bfc9SLarry Finger 	u32 counter = 0;
68b1a3bfc9SLarry Finger 	u32 value32;
69b1a3bfc9SLarry Finger 
70b1a3bfc9SLarry Finger 	do {
71b1a3bfc9SLarry Finger 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
72b1a3bfc9SLarry Finger 	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
73b1a3bfc9SLarry Finger 		 (!(value32 & FWDL_CHKSUM_RPT)));
74b1a3bfc9SLarry Finger 
75b1a3bfc9SLarry Finger 	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
76a44f59d6SLarry Finger 		pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
77b1a3bfc9SLarry Finger 		       value32);
78b1a3bfc9SLarry Finger 		goto exit;
79b1a3bfc9SLarry Finger 	}
80b1a3bfc9SLarry Finger 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
81b1a3bfc9SLarry Finger 	value32 |= MCUFWDL_RDY;
82b1a3bfc9SLarry Finger 	value32 &= ~WINTINI_RDY;
83b1a3bfc9SLarry Finger 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
84b1a3bfc9SLarry Finger 
85b1a3bfc9SLarry Finger 	rtl92ee_firmware_selfreset(hw);
86b1a3bfc9SLarry Finger 	counter = 0;
87b1a3bfc9SLarry Finger 
88b1a3bfc9SLarry Finger 	do {
89b1a3bfc9SLarry Finger 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
90c93ac39dSLarry Finger 		if (value32 & WINTINI_RDY)
91c93ac39dSLarry Finger 			return 0;
92b1a3bfc9SLarry Finger 
93b1a3bfc9SLarry Finger 		udelay(FW_8192C_POLLING_DELAY*10);
94b1a3bfc9SLarry Finger 
95b1a3bfc9SLarry Finger 	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
96b1a3bfc9SLarry Finger 
97a44f59d6SLarry Finger 	pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
98b1a3bfc9SLarry Finger 	       value32, counter);
99b1a3bfc9SLarry Finger 
100b1a3bfc9SLarry Finger exit:
101b1a3bfc9SLarry Finger 	return err;
102b1a3bfc9SLarry Finger }
103b1a3bfc9SLarry Finger 
rtl92ee_download_fw(struct ieee80211_hw * hw,bool buse_wake_on_wlan_fw)104b1a3bfc9SLarry Finger int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
105b1a3bfc9SLarry Finger {
106b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
107b1a3bfc9SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1088d882bcfSLarry Finger 	struct rtlwifi_firmware_header *pfwheader;
109b1a3bfc9SLarry Finger 	u8 *pfwdata;
110b1a3bfc9SLarry Finger 	u32 fwsize;
111b1a3bfc9SLarry Finger 	enum version_8192e version = rtlhal->version;
112b1a3bfc9SLarry Finger 
113b1a3bfc9SLarry Finger 	if (!rtlhal->pfirmware)
114b1a3bfc9SLarry Finger 		return 1;
115b1a3bfc9SLarry Finger 
1168d882bcfSLarry Finger 	pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
1178d882bcfSLarry Finger 	rtlhal->fw_version = le16_to_cpu(pfwheader->version);
118b1a3bfc9SLarry Finger 	rtlhal->fw_subversion = pfwheader->subversion;
119b1a3bfc9SLarry Finger 	pfwdata = (u8 *)rtlhal->pfirmware;
120b1a3bfc9SLarry Finger 	fwsize = rtlhal->fwsize;
121e24a2a87SLarry Finger 	rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
122b1a3bfc9SLarry Finger 		"normal Firmware SIZE %d\n", fwsize);
123b1a3bfc9SLarry Finger 
124b1a3bfc9SLarry Finger 	if (IS_FW_HEADER_EXIST(pfwheader)) {
125e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
126b1a3bfc9SLarry Finger 			"Firmware Version(%d), Signature(%#x),Size(%d)\n",
127b1a3bfc9SLarry Finger 			pfwheader->version, pfwheader->signature,
1288d882bcfSLarry Finger 			(int)sizeof(struct rtlwifi_firmware_header));
129b1a3bfc9SLarry Finger 
1308d882bcfSLarry Finger 		pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
1318d882bcfSLarry Finger 		fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
132b1a3bfc9SLarry Finger 	} else {
133e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
134b1a3bfc9SLarry Finger 			"Firmware no Header, Signature(%#x)\n",
135b1a3bfc9SLarry Finger 			pfwheader->signature);
136b1a3bfc9SLarry Finger 	}
137b1a3bfc9SLarry Finger 
138b1a3bfc9SLarry Finger 	if (rtlhal->mac_func_enable) {
139b1a3bfc9SLarry Finger 		if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
140b1a3bfc9SLarry Finger 			rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
141b1a3bfc9SLarry Finger 			rtl92ee_firmware_selfreset(hw);
142b1a3bfc9SLarry Finger 		}
143b1a3bfc9SLarry Finger 	}
144b1a3bfc9SLarry Finger 	_rtl92ee_enable_fw_download(hw, true);
145b1a3bfc9SLarry Finger 	_rtl92ee_write_fw(hw, version, pfwdata, fwsize);
146b1a3bfc9SLarry Finger 	_rtl92ee_enable_fw_download(hw, false);
147b1a3bfc9SLarry Finger 
14859f4567dSzhengbin 	return _rtl92ee_fw_free_to_go(hw);
149b1a3bfc9SLarry Finger }
150b1a3bfc9SLarry Finger 
_rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw * hw,u8 boxnum)151b1a3bfc9SLarry Finger static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
152b1a3bfc9SLarry Finger {
153b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
154b1a3bfc9SLarry Finger 	u8 val_hmetfr;
155b1a3bfc9SLarry Finger 	bool result = false;
156b1a3bfc9SLarry Finger 
157b1a3bfc9SLarry Finger 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
158b1a3bfc9SLarry Finger 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
159b1a3bfc9SLarry Finger 		result = true;
160b1a3bfc9SLarry Finger 	return result;
161b1a3bfc9SLarry Finger }
162b1a3bfc9SLarry Finger 
_rtl92ee_fill_h2c_command(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)163b1a3bfc9SLarry Finger static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
164b1a3bfc9SLarry Finger 				      u32 cmd_len, u8 *cmdbuffer)
165b1a3bfc9SLarry Finger {
166b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
167b1a3bfc9SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
168b1a3bfc9SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
169b1a3bfc9SLarry Finger 	u8 boxnum;
170b1a3bfc9SLarry Finger 	u16 box_reg = 0, box_extreg = 0;
171b1a3bfc9SLarry Finger 	u8 u1b_tmp;
172b1a3bfc9SLarry Finger 	bool isfw_read = false;
173b1a3bfc9SLarry Finger 	u8 buf_index = 0;
174b1a3bfc9SLarry Finger 	bool bwrite_sucess = false;
175b1a3bfc9SLarry Finger 	u8 wait_h2c_limmit = 100;
176b1a3bfc9SLarry Finger 	u8 boxcontent[4], boxextcontent[4];
177b1a3bfc9SLarry Finger 	u32 h2c_waitcounter = 0;
178b1a3bfc9SLarry Finger 	unsigned long flag;
179b1a3bfc9SLarry Finger 	u8 idx;
180b1a3bfc9SLarry Finger 
181b1a3bfc9SLarry Finger 	if (ppsc->dot11_psmode != EACTIVE ||
182b1a3bfc9SLarry Finger 	    ppsc->inactive_pwrstate == ERFOFF) {
183e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
184b1a3bfc9SLarry Finger 			"FillH2CCommand8192E(): Return because RF is off!!!\n");
185b1a3bfc9SLarry Finger 		return;
186b1a3bfc9SLarry Finger 	}
187b1a3bfc9SLarry Finger 
188e24a2a87SLarry Finger 	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
189b1a3bfc9SLarry Finger 
190b1a3bfc9SLarry Finger 	/* 1. Prevent race condition in setting H2C cmd.
191b1a3bfc9SLarry Finger 	 * (copy from MgntActSet_RF_State().)
192b1a3bfc9SLarry Finger 	 */
193b1a3bfc9SLarry Finger 	while (true) {
194b1a3bfc9SLarry Finger 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
195b1a3bfc9SLarry Finger 		if (rtlhal->h2c_setinprogress) {
196e24a2a87SLarry Finger 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
197b1a3bfc9SLarry Finger 				"H2C set in progress! Wait to set..element_id(%d).\n",
198b1a3bfc9SLarry Finger 				element_id);
199b1a3bfc9SLarry Finger 
200b1a3bfc9SLarry Finger 			while (rtlhal->h2c_setinprogress) {
201b1a3bfc9SLarry Finger 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
202b1a3bfc9SLarry Finger 						       flag);
203b1a3bfc9SLarry Finger 				h2c_waitcounter++;
204e24a2a87SLarry Finger 				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
205b1a3bfc9SLarry Finger 					"Wait 100 us (%d times)...\n",
206b1a3bfc9SLarry Finger 					h2c_waitcounter);
207b1a3bfc9SLarry Finger 				udelay(100);
208b1a3bfc9SLarry Finger 
209b1a3bfc9SLarry Finger 				if (h2c_waitcounter > 1000)
210b1a3bfc9SLarry Finger 					return;
211b1a3bfc9SLarry Finger 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
212b1a3bfc9SLarry Finger 						  flag);
213b1a3bfc9SLarry Finger 			}
214b1a3bfc9SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
215b1a3bfc9SLarry Finger 		} else {
216b1a3bfc9SLarry Finger 			rtlhal->h2c_setinprogress = true;
217b1a3bfc9SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
218b1a3bfc9SLarry Finger 			break;
219b1a3bfc9SLarry Finger 		}
220b1a3bfc9SLarry Finger 	}
221b1a3bfc9SLarry Finger 
222b1a3bfc9SLarry Finger 	while (!bwrite_sucess) {
223b1a3bfc9SLarry Finger 		/* 2. Find the last BOX number which has been writen. */
224b1a3bfc9SLarry Finger 		boxnum = rtlhal->last_hmeboxnum;
225b1a3bfc9SLarry Finger 		switch (boxnum) {
226b1a3bfc9SLarry Finger 		case 0:
227b1a3bfc9SLarry Finger 			box_reg = REG_HMEBOX_0;
228b1a3bfc9SLarry Finger 			box_extreg = REG_HMEBOX_EXT_0;
229b1a3bfc9SLarry Finger 			break;
230b1a3bfc9SLarry Finger 		case 1:
231b1a3bfc9SLarry Finger 			box_reg = REG_HMEBOX_1;
232b1a3bfc9SLarry Finger 			box_extreg = REG_HMEBOX_EXT_1;
233b1a3bfc9SLarry Finger 			break;
234b1a3bfc9SLarry Finger 		case 2:
235b1a3bfc9SLarry Finger 			box_reg = REG_HMEBOX_2;
236b1a3bfc9SLarry Finger 			box_extreg = REG_HMEBOX_EXT_2;
237b1a3bfc9SLarry Finger 			break;
238b1a3bfc9SLarry Finger 		case 3:
239b1a3bfc9SLarry Finger 			box_reg = REG_HMEBOX_3;
240b1a3bfc9SLarry Finger 			box_extreg = REG_HMEBOX_EXT_3;
241b1a3bfc9SLarry Finger 			break;
242b1a3bfc9SLarry Finger 		default:
243e24a2a87SLarry Finger 			rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
244ad574889SJoe Perches 				"switch case %#x not processed\n", boxnum);
245b1a3bfc9SLarry Finger 			break;
246b1a3bfc9SLarry Finger 		}
247b1a3bfc9SLarry Finger 
248b1a3bfc9SLarry Finger 		/* 3. Check if the box content is empty. */
249b1a3bfc9SLarry Finger 		isfw_read = false;
250b1a3bfc9SLarry Finger 		u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
251b1a3bfc9SLarry Finger 
252b1a3bfc9SLarry Finger 		if (u1b_tmp != 0xea) {
253b1a3bfc9SLarry Finger 			isfw_read = true;
254b1a3bfc9SLarry Finger 		} else {
255b1a3bfc9SLarry Finger 			if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
256b1a3bfc9SLarry Finger 			    rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
257b1a3bfc9SLarry Finger 				rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
258b1a3bfc9SLarry Finger 		}
259b1a3bfc9SLarry Finger 
260b1a3bfc9SLarry Finger 		if (isfw_read) {
261b1a3bfc9SLarry Finger 			wait_h2c_limmit = 100;
262b1a3bfc9SLarry Finger 			isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
263b1a3bfc9SLarry Finger 			while (!isfw_read) {
264b1a3bfc9SLarry Finger 				wait_h2c_limmit--;
265b1a3bfc9SLarry Finger 				if (wait_h2c_limmit == 0) {
266e24a2a87SLarry Finger 					rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
267b1a3bfc9SLarry Finger 						"Waiting too long for FW read clear HMEBox(%d)!!!\n",
268b1a3bfc9SLarry Finger 						boxnum);
269b1a3bfc9SLarry Finger 					break;
270b1a3bfc9SLarry Finger 				}
271b1a3bfc9SLarry Finger 				udelay(10);
272b1a3bfc9SLarry Finger 				isfw_read =
273b1a3bfc9SLarry Finger 				  _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
274b1a3bfc9SLarry Finger 				u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
275e24a2a87SLarry Finger 				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
276b1a3bfc9SLarry Finger 					"Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
277b1a3bfc9SLarry Finger 					boxnum, u1b_tmp);
278b1a3bfc9SLarry Finger 			}
279b1a3bfc9SLarry Finger 		}
280b1a3bfc9SLarry Finger 
281b1a3bfc9SLarry Finger 		/* If Fw has not read the last
282b1a3bfc9SLarry Finger 		 * H2C cmd, break and give up this H2C.
283b1a3bfc9SLarry Finger 		 */
284b1a3bfc9SLarry Finger 		if (!isfw_read) {
285e24a2a87SLarry Finger 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
286b1a3bfc9SLarry Finger 				"Write H2C reg BOX[%d] fail,Fw don't read.\n",
287b1a3bfc9SLarry Finger 				boxnum);
288b1a3bfc9SLarry Finger 			break;
289b1a3bfc9SLarry Finger 		}
290b1a3bfc9SLarry Finger 		/* 4. Fill the H2C cmd into box */
291b1a3bfc9SLarry Finger 		memset(boxcontent, 0, sizeof(boxcontent));
292b1a3bfc9SLarry Finger 		memset(boxextcontent, 0, sizeof(boxextcontent));
293b1a3bfc9SLarry Finger 		boxcontent[0] = element_id;
294e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
295b1a3bfc9SLarry Finger 			"Write element_id box_reg(%4x) = %2x\n",
296b1a3bfc9SLarry Finger 			box_reg, element_id);
297b1a3bfc9SLarry Finger 
298b1a3bfc9SLarry Finger 		switch (cmd_len) {
299b1a3bfc9SLarry Finger 		case 1:
300b1a3bfc9SLarry Finger 		case 2:
301b1a3bfc9SLarry Finger 		case 3:
302b1a3bfc9SLarry Finger 			/*boxcontent[0] &= ~(BIT(7));*/
303b1a3bfc9SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
304b1a3bfc9SLarry Finger 			       cmdbuffer + buf_index, cmd_len);
305b1a3bfc9SLarry Finger 
306b1a3bfc9SLarry Finger 			for (idx = 0; idx < 4; idx++) {
307b1a3bfc9SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
308b1a3bfc9SLarry Finger 					       boxcontent[idx]);
309b1a3bfc9SLarry Finger 			}
310b1a3bfc9SLarry Finger 			break;
311b1a3bfc9SLarry Finger 		case 4:
312b1a3bfc9SLarry Finger 		case 5:
313b1a3bfc9SLarry Finger 		case 6:
314b1a3bfc9SLarry Finger 		case 7:
315b1a3bfc9SLarry Finger 			/*boxcontent[0] |= (BIT(7));*/
316b1a3bfc9SLarry Finger 			memcpy((u8 *)(boxextcontent),
317b1a3bfc9SLarry Finger 			       cmdbuffer + buf_index+3, cmd_len-3);
318b1a3bfc9SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
319b1a3bfc9SLarry Finger 			       cmdbuffer + buf_index, 3);
320b1a3bfc9SLarry Finger 
321b1a3bfc9SLarry Finger 			for (idx = 0; idx < 4; idx++) {
322b1a3bfc9SLarry Finger 				rtl_write_byte(rtlpriv, box_extreg + idx,
323b1a3bfc9SLarry Finger 					       boxextcontent[idx]);
324b1a3bfc9SLarry Finger 			}
325b1a3bfc9SLarry Finger 
326b1a3bfc9SLarry Finger 			for (idx = 0; idx < 4; idx++) {
327b1a3bfc9SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
328b1a3bfc9SLarry Finger 					       boxcontent[idx]);
329b1a3bfc9SLarry Finger 			}
330b1a3bfc9SLarry Finger 			break;
331b1a3bfc9SLarry Finger 		default:
332e24a2a87SLarry Finger 			rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
333ad574889SJoe Perches 				"switch case %#x not processed\n", cmd_len);
334b1a3bfc9SLarry Finger 			break;
335b1a3bfc9SLarry Finger 		}
336b1a3bfc9SLarry Finger 
337b1a3bfc9SLarry Finger 		bwrite_sucess = true;
338b1a3bfc9SLarry Finger 
339b1a3bfc9SLarry Finger 		rtlhal->last_hmeboxnum = boxnum + 1;
340b1a3bfc9SLarry Finger 		if (rtlhal->last_hmeboxnum == 4)
341b1a3bfc9SLarry Finger 			rtlhal->last_hmeboxnum = 0;
342b1a3bfc9SLarry Finger 
343e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
344b1a3bfc9SLarry Finger 			"pHalData->last_hmeboxnum  = %d\n",
345b1a3bfc9SLarry Finger 			rtlhal->last_hmeboxnum);
346b1a3bfc9SLarry Finger 	}
347b1a3bfc9SLarry Finger 
348b1a3bfc9SLarry Finger 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
349b1a3bfc9SLarry Finger 	rtlhal->h2c_setinprogress = false;
350b1a3bfc9SLarry Finger 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
351b1a3bfc9SLarry Finger 
352e24a2a87SLarry Finger 	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
353b1a3bfc9SLarry Finger }
354b1a3bfc9SLarry Finger 
rtl92ee_fill_h2c_cmd(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)355b1a3bfc9SLarry Finger void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
356b1a3bfc9SLarry Finger 			  u8 element_id, u32 cmd_len, u8 *cmdbuffer)
357b1a3bfc9SLarry Finger {
358b1a3bfc9SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
359b1a3bfc9SLarry Finger 	u32 tmp_cmdbuf[2];
360b1a3bfc9SLarry Finger 
361b1a3bfc9SLarry Finger 	if (!rtlhal->fw_ready) {
362531940f9SLarry Finger 		WARN_ONCE(true,
363531940f9SLarry Finger 			  "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
364b1a3bfc9SLarry Finger 		return;
365b1a3bfc9SLarry Finger 	}
366b1a3bfc9SLarry Finger 
367b1a3bfc9SLarry Finger 	memset(tmp_cmdbuf, 0, 8);
368b1a3bfc9SLarry Finger 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
369b1a3bfc9SLarry Finger 	_rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
370b1a3bfc9SLarry Finger }
371b1a3bfc9SLarry Finger 
rtl92ee_firmware_selfreset(struct ieee80211_hw * hw)372b1a3bfc9SLarry Finger void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
373b1a3bfc9SLarry Finger {
374b1a3bfc9SLarry Finger 	u8 u1b_tmp;
375b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
376b1a3bfc9SLarry Finger 
377b1a3bfc9SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
378b1a3bfc9SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
379b1a3bfc9SLarry Finger 
380b1a3bfc9SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
381b1a3bfc9SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
382b1a3bfc9SLarry Finger 
383b1a3bfc9SLarry Finger 	udelay(50);
384b1a3bfc9SLarry Finger 
385b1a3bfc9SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
386b1a3bfc9SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
387b1a3bfc9SLarry Finger 
388b1a3bfc9SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
389b1a3bfc9SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
390b1a3bfc9SLarry Finger 
391e24a2a87SLarry Finger 	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
392b1a3bfc9SLarry Finger 		"  _8051Reset92E(): 8051 reset success .\n");
393b1a3bfc9SLarry Finger }
394b1a3bfc9SLarry Finger 
rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw * hw,u8 mode)395b1a3bfc9SLarry Finger void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
396b1a3bfc9SLarry Finger {
397b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
398b1a3bfc9SLarry Finger 	u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
399b1a3bfc9SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
40042213f2fSPing-Ke Shih 	u8 rlbm, power_state = 0, byte5 = 0;
40142213f2fSPing-Ke Shih 	u8 awake_intvl;	/* DTIM = (awake_intvl - 1) */
40254685f9cSPing-Ke Shih 	struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
40342213f2fSPing-Ke Shih 	bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
40442213f2fSPing-Ke Shih 			    btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
405135f4fbdSPing-Ke Shih 	bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
406135f4fbdSPing-Ke Shih 			  btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
407135f4fbdSPing-Ke Shih 
408135f4fbdSPing-Ke Shih 	if (bt_ctrl_lps)
409135f4fbdSPing-Ke Shih 		mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
410b1a3bfc9SLarry Finger 
411e24a2a87SLarry Finger 	rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
41242213f2fSPing-Ke Shih 		mode, bt_ctrl_lps);
41342213f2fSPing-Ke Shih 
41442213f2fSPing-Ke Shih 	switch (mode) {
41542213f2fSPing-Ke Shih 	case FW_PS_MIN_MODE:
41642213f2fSPing-Ke Shih 		rlbm = 0;
41742213f2fSPing-Ke Shih 		awake_intvl = 2;
41842213f2fSPing-Ke Shih 		break;
41942213f2fSPing-Ke Shih 	case FW_PS_MAX_MODE:
42042213f2fSPing-Ke Shih 		rlbm = 1;
42142213f2fSPing-Ke Shih 		awake_intvl = 2;
42242213f2fSPing-Ke Shih 		break;
42342213f2fSPing-Ke Shih 	case FW_PS_DTIM_MODE:
42442213f2fSPing-Ke Shih 		rlbm = 2;
42542213f2fSPing-Ke Shih 		awake_intvl = ppsc->reg_max_lps_awakeintvl;
42642213f2fSPing-Ke Shih 		/* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
42742213f2fSPing-Ke Shih 		 * is only used in swlps.
42842213f2fSPing-Ke Shih 		 */
42942213f2fSPing-Ke Shih 		break;
43042213f2fSPing-Ke Shih 	default:
43142213f2fSPing-Ke Shih 		rlbm = 2;
43242213f2fSPing-Ke Shih 		awake_intvl = 4;
43342213f2fSPing-Ke Shih 		break;
43442213f2fSPing-Ke Shih 	}
43542213f2fSPing-Ke Shih 
43642213f2fSPing-Ke Shih 	if (rtlpriv->mac80211.p2p) {
43742213f2fSPing-Ke Shih 		awake_intvl = 2;
43842213f2fSPing-Ke Shih 		rlbm = 1;
43942213f2fSPing-Ke Shih 	}
44042213f2fSPing-Ke Shih 
44142213f2fSPing-Ke Shih 	if (mode == FW_PS_ACTIVE_MODE) {
44242213f2fSPing-Ke Shih 		byte5 = 0x40;
44342213f2fSPing-Ke Shih 		power_state = FW_PWR_STATE_ACTIVE;
44442213f2fSPing-Ke Shih 	} else {
44542213f2fSPing-Ke Shih 		if (bt_ctrl_lps) {
44642213f2fSPing-Ke Shih 			byte5 = btc_ops->btc_get_lps_val(rtlpriv);
44742213f2fSPing-Ke Shih 			power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
44842213f2fSPing-Ke Shih 
44942213f2fSPing-Ke Shih 			if ((rlbm == 2) && (byte5 & BIT(4))) {
45042213f2fSPing-Ke Shih 				/* Keep awake interval to 1 to prevent from
45142213f2fSPing-Ke Shih 				 * decreasing coex performance
45242213f2fSPing-Ke Shih 				 */
45342213f2fSPing-Ke Shih 				awake_intvl = 2;
45442213f2fSPing-Ke Shih 				rlbm = 2;
45542213f2fSPing-Ke Shih 			}
45642213f2fSPing-Ke Shih 		} else {
45742213f2fSPing-Ke Shih 			byte5 = 0x40;
45842213f2fSPing-Ke Shih 			power_state = FW_PWR_STATE_RF_OFF;
45942213f2fSPing-Ke Shih 		}
46042213f2fSPing-Ke Shih 	}
461b1a3bfc9SLarry Finger 
462b1a3bfc9SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
463b1a3bfc9SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
464b1a3bfc9SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
465135f4fbdSPing-Ke Shih 					 bt_ctrl_lps ? 0 :
466135f4fbdSPing-Ke Shih 					 ((rtlpriv->mac80211.p2p) ?
467135f4fbdSPing-Ke Shih 					  ppsc->smart_ps : 1));
468b1a3bfc9SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
46942213f2fSPing-Ke Shih 					       awake_intvl);
470b1a3bfc9SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
471b1a3bfc9SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
47254685f9cSPing-Ke Shih 	SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
473b1a3bfc9SLarry Finger 
474b1a3bfc9SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
475b1a3bfc9SLarry Finger 		      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
476b1a3bfc9SLarry Finger 		      u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
47754685f9cSPing-Ke Shih 	if (rtlpriv->cfg->ops->get_btc_status())
47854685f9cSPing-Ke Shih 		btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
47954685f9cSPing-Ke Shih 					     H2C_92E_PWEMODE_LENGTH);
480b1a3bfc9SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
481b1a3bfc9SLarry Finger 			     u1_h2c_set_pwrmode);
482b1a3bfc9SLarry Finger }
483b1a3bfc9SLarry Finger 
rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw * hw,u8 mstatus)484b1a3bfc9SLarry Finger void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
485b1a3bfc9SLarry Finger {
486b1a3bfc9SLarry Finger 	u8 parm[3] = { 0 , 0 , 0 };
487b1a3bfc9SLarry Finger 	/* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
488b1a3bfc9SLarry Finger 	 *          bit1=0-->update Media Status to MACID
489b1a3bfc9SLarry Finger 	 *          bit1=1-->update Media Status from MACID to MACID_End
490b1a3bfc9SLarry Finger 	 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
491b1a3bfc9SLarry Finger 	 * parm[2]: MACID_End
492b1a3bfc9SLarry Finger 	 */
493b1a3bfc9SLarry Finger 
494b1a3bfc9SLarry Finger 	SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
495b1a3bfc9SLarry Finger 	SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
496b1a3bfc9SLarry Finger 
497b1a3bfc9SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
498b1a3bfc9SLarry Finger }
499b1a3bfc9SLarry Finger 
500b1a3bfc9SLarry Finger #define BEACON_PG		0 /* ->1 */
501b1a3bfc9SLarry Finger #define PSPOLL_PG		2
502b1a3bfc9SLarry Finger #define NULL_PG			3
503b1a3bfc9SLarry Finger #define PROBERSP_PG		4 /* ->5 */
50474a7dfbcSPing-Ke Shih #define QOS_NULL_PG		6
50574a7dfbcSPing-Ke Shih #define BT_QOS_NULL_PG	7
506b1a3bfc9SLarry Finger 
50774a7dfbcSPing-Ke Shih #define TOTAL_RESERVED_PKT_LEN	1024
508b1a3bfc9SLarry Finger 
509b1a3bfc9SLarry Finger static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
510b1a3bfc9SLarry Finger 	/* page 0 beacon */
511b1a3bfc9SLarry Finger 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
512b1a3bfc9SLarry Finger 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
513b1a3bfc9SLarry Finger 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
514b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515b1a3bfc9SLarry Finger 	0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
516b1a3bfc9SLarry Finger 	0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
517b1a3bfc9SLarry Finger 	0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
518b1a3bfc9SLarry Finger 	0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
519b1a3bfc9SLarry Finger 	0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
520b1a3bfc9SLarry Finger 	0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
521b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523b1a3bfc9SLarry Finger 	0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
524b1a3bfc9SLarry Finger 	0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
525b1a3bfc9SLarry Finger 	0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
526b1a3bfc9SLarry Finger 	0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
527b1a3bfc9SLarry Finger 
528b1a3bfc9SLarry Finger 	/* page 1 beacon */
529b1a3bfc9SLarry Finger 	0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
530b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540b1a3bfc9SLarry Finger 	0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
541b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
542b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545b1a3bfc9SLarry Finger 
546b1a3bfc9SLarry Finger 	/* page 2  ps-poll */
547b1a3bfc9SLarry Finger 	0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
548b1a3bfc9SLarry Finger 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
549b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558b1a3bfc9SLarry Finger 	0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
559b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
560b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562b1a3bfc9SLarry Finger 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563b1a3bfc9SLarry Finger 
564b1a3bfc9SLarry Finger 	/* page 3  null */
565b1a3bfc9SLarry Finger 	0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
566b1a3bfc9SLarry Finger 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
567b1a3bfc9SLarry Finger 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
568b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576b1a3bfc9SLarry Finger 	0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
577b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
578b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580b1a3bfc9SLarry Finger 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581b1a3bfc9SLarry Finger 
582b1a3bfc9SLarry Finger 	/* page 4  probe_resp */
583b1a3bfc9SLarry Finger 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
584b1a3bfc9SLarry Finger 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
585b1a3bfc9SLarry Finger 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
586b1a3bfc9SLarry Finger 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
587b1a3bfc9SLarry Finger 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
588b1a3bfc9SLarry Finger 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
589b1a3bfc9SLarry Finger 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
590b1a3bfc9SLarry Finger 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
591b1a3bfc9SLarry Finger 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
592b1a3bfc9SLarry Finger 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
593b1a3bfc9SLarry Finger 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596b1a3bfc9SLarry Finger 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
597b1a3bfc9SLarry Finger 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599b1a3bfc9SLarry Finger 
600b1a3bfc9SLarry Finger 	/* page 5  probe_resp */
601b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60874a7dfbcSPing-Ke Shih 	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
60974a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
61074a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61174a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61274a7dfbcSPing-Ke Shih 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61374a7dfbcSPing-Ke Shih 
61474a7dfbcSPing-Ke Shih 	/* page 6 qos null data */
61574a7dfbcSPing-Ke Shih 	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
61674a7dfbcSPing-Ke Shih 	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
61774a7dfbcSPing-Ke Shih 	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
61874a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61974a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62074a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62174a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62274a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62374a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62474a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62574a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62674a7dfbcSPing-Ke Shih 	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
62774a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
62874a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62974a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63074a7dfbcSPing-Ke Shih 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63174a7dfbcSPing-Ke Shih 
63274a7dfbcSPing-Ke Shih 	/* page 7 BT-qos null data */
63374a7dfbcSPing-Ke Shih 	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
63474a7dfbcSPing-Ke Shih 	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
63574a7dfbcSPing-Ke Shih 	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
63674a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63774a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63874a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63974a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64074a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64174a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64274a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64374a7dfbcSPing-Ke Shih 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652b1a3bfc9SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653b1a3bfc9SLarry Finger };
654b1a3bfc9SLarry Finger 
rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw * hw,bool b_dl_finished)655b1a3bfc9SLarry Finger void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
656b1a3bfc9SLarry Finger {
657b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
658b1a3bfc9SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
659b1a3bfc9SLarry Finger 	struct sk_buff *skb = NULL;
660519ce2f9SLarry Finger 	bool rtstatus;
661b1a3bfc9SLarry Finger 	u32 totalpacketlen;
662b1a3bfc9SLarry Finger 	u8 u1rsvdpageloc[5] = { 0 };
663b1a3bfc9SLarry Finger 	bool b_dlok = false;
664b1a3bfc9SLarry Finger 
665b1a3bfc9SLarry Finger 	u8 *beacon;
666b1a3bfc9SLarry Finger 	u8 *p_pspoll;
667b1a3bfc9SLarry Finger 	u8 *nullfunc;
668b1a3bfc9SLarry Finger 	u8 *p_probersp;
66974a7dfbcSPing-Ke Shih 	u8 *qosnull;
67074a7dfbcSPing-Ke Shih 	u8 *btqosnull;
671b1a3bfc9SLarry Finger 	/*---------------------------------------------------------
672b1a3bfc9SLarry Finger 	 *			(1) beacon
673b1a3bfc9SLarry Finger 	 *---------------------------------------------------------
674b1a3bfc9SLarry Finger 	 */
675b1a3bfc9SLarry Finger 	beacon = &reserved_page_packet[BEACON_PG * 128];
676b1a3bfc9SLarry Finger 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
677b1a3bfc9SLarry Finger 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
678b1a3bfc9SLarry Finger 
679b1a3bfc9SLarry Finger 	/*-------------------------------------------------------
680b1a3bfc9SLarry Finger 	 *			(2) ps-poll
681b1a3bfc9SLarry Finger 	 *--------------------------------------------------------
682b1a3bfc9SLarry Finger 	 */
683b1a3bfc9SLarry Finger 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
684b1a3bfc9SLarry Finger 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
685b1a3bfc9SLarry Finger 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
686b1a3bfc9SLarry Finger 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
687b1a3bfc9SLarry Finger 
688b1a3bfc9SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
689b1a3bfc9SLarry Finger 
690b1a3bfc9SLarry Finger 	/*--------------------------------------------------------
691b1a3bfc9SLarry Finger 	 *			(3) null data
692b1a3bfc9SLarry Finger 	 *---------------------------------------------------------
693b1a3bfc9SLarry Finger 	 */
694b1a3bfc9SLarry Finger 	nullfunc = &reserved_page_packet[NULL_PG * 128];
695b1a3bfc9SLarry Finger 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
696b1a3bfc9SLarry Finger 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
697b1a3bfc9SLarry Finger 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
698b1a3bfc9SLarry Finger 
699b1a3bfc9SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
700b1a3bfc9SLarry Finger 
701b1a3bfc9SLarry Finger 	/*---------------------------------------------------------
702b1a3bfc9SLarry Finger 	 *			(4) probe response
703b1a3bfc9SLarry Finger 	 *----------------------------------------------------------
704b1a3bfc9SLarry Finger 	 */
705b1a3bfc9SLarry Finger 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
706b1a3bfc9SLarry Finger 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
707b1a3bfc9SLarry Finger 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
708b1a3bfc9SLarry Finger 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
709b1a3bfc9SLarry Finger 
710b1a3bfc9SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
711b1a3bfc9SLarry Finger 
71274a7dfbcSPing-Ke Shih 	/*---------------------------------------------------------
71374a7dfbcSPing-Ke Shih 	 *			(5) QoS null data
71474a7dfbcSPing-Ke Shih 	 *----------------------------------------------------------
71574a7dfbcSPing-Ke Shih 	 */
71674a7dfbcSPing-Ke Shih 	qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
71774a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
71874a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
71974a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
72074a7dfbcSPing-Ke Shih 
72174a7dfbcSPing-Ke Shih 	SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
72274a7dfbcSPing-Ke Shih 
72374a7dfbcSPing-Ke Shih 	/*---------------------------------------------------------
72474a7dfbcSPing-Ke Shih 	 *			(6) BT QoS null data
72574a7dfbcSPing-Ke Shih 	 *----------------------------------------------------------
72674a7dfbcSPing-Ke Shih 	 */
72774a7dfbcSPing-Ke Shih 	btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
72874a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
72974a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
73074a7dfbcSPing-Ke Shih 	SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
73174a7dfbcSPing-Ke Shih 
73274a7dfbcSPing-Ke Shih 	SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
73374a7dfbcSPing-Ke Shih 
734b1a3bfc9SLarry Finger 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
735b1a3bfc9SLarry Finger 
736b1a3bfc9SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
737b1a3bfc9SLarry Finger 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
738b1a3bfc9SLarry Finger 		      &reserved_page_packet[0], totalpacketlen);
739b1a3bfc9SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
740b1a3bfc9SLarry Finger 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
741b1a3bfc9SLarry Finger 		      u1rsvdpageloc, 3);
742b1a3bfc9SLarry Finger 
743b1a3bfc9SLarry Finger 	skb = dev_alloc_skb(totalpacketlen);
74460209d48SPing-Ke Shih 	if (!skb)
74560209d48SPing-Ke Shih 		return;
746ad941e69Syuan linyu 	skb_put_data(skb, &reserved_page_packet, totalpacketlen);
747b1a3bfc9SLarry Finger 
748519ce2f9SLarry Finger 	rtstatus = rtl_cmd_send_packet(hw, skb);
749519ce2f9SLarry Finger 	if (rtstatus)
750b1a3bfc9SLarry Finger 		b_dlok = true;
751b1a3bfc9SLarry Finger 
752b1a3bfc9SLarry Finger 	if (b_dlok) {
753e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
754b1a3bfc9SLarry Finger 			"Set RSVD page location to Fw.\n");
755b1a3bfc9SLarry Finger 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
756b1a3bfc9SLarry Finger 			      "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
757b1a3bfc9SLarry Finger 		rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
758b1a3bfc9SLarry Finger 				     sizeof(u1rsvdpageloc), u1rsvdpageloc);
759b1a3bfc9SLarry Finger 	} else {
760e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
761b1a3bfc9SLarry Finger 			"Set RSVD page location to Fw FAIL!!!!!!.\n");
762b1a3bfc9SLarry Finger 	}
763b1a3bfc9SLarry Finger }
764b1a3bfc9SLarry Finger 
765b1a3bfc9SLarry Finger /*Shoud check FW support p2p or not.*/
rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw * hw,u8 ctwindow)766b1a3bfc9SLarry Finger static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
767b1a3bfc9SLarry Finger {
768b1a3bfc9SLarry Finger 	u8 u1_ctwindow_period[1] = {ctwindow};
769b1a3bfc9SLarry Finger 
770b1a3bfc9SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
771b1a3bfc9SLarry Finger }
772b1a3bfc9SLarry Finger 
rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw * hw,u8 p2p_ps_state)773b1a3bfc9SLarry Finger void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
774b1a3bfc9SLarry Finger {
775b1a3bfc9SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
776b1a3bfc9SLarry Finger 	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
777b1a3bfc9SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
778b1a3bfc9SLarry Finger 	struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
779b1a3bfc9SLarry Finger 	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
780b1a3bfc9SLarry Finger 	u8 i;
781b1a3bfc9SLarry Finger 	u16 ctwindow;
782b1a3bfc9SLarry Finger 	u32 start_time, tsf_low;
783b1a3bfc9SLarry Finger 
784b1a3bfc9SLarry Finger 	switch (p2p_ps_state) {
785b1a3bfc9SLarry Finger 	case P2P_PS_DISABLE:
786e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
787b1a3bfc9SLarry Finger 		memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
788b1a3bfc9SLarry Finger 		break;
789b1a3bfc9SLarry Finger 	case P2P_PS_ENABLE:
790e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
791b1a3bfc9SLarry Finger 		/* update CTWindow value. */
792b1a3bfc9SLarry Finger 		if (p2pinfo->ctwindow > 0) {
793b1a3bfc9SLarry Finger 			p2p_ps_offload->ctwindow_en = 1;
794b1a3bfc9SLarry Finger 			ctwindow = p2pinfo->ctwindow;
795b1a3bfc9SLarry Finger 			rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
796b1a3bfc9SLarry Finger 		}
797b1a3bfc9SLarry Finger 		/* hw only support 2 set of NoA */
798b1a3bfc9SLarry Finger 		for (i = 0 ; i < p2pinfo->noa_num ; i++) {
799b1a3bfc9SLarry Finger 			/* To control the register setting for which NOA*/
800b1a3bfc9SLarry Finger 			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
801b1a3bfc9SLarry Finger 			if (i == 0)
802b1a3bfc9SLarry Finger 				p2p_ps_offload->noa0_en = 1;
803b1a3bfc9SLarry Finger 			else
804b1a3bfc9SLarry Finger 				p2p_ps_offload->noa1_en = 1;
805b1a3bfc9SLarry Finger 			/* config P2P NoA Descriptor Register */
806b1a3bfc9SLarry Finger 			rtl_write_dword(rtlpriv, 0x5E0,
807b1a3bfc9SLarry Finger 					p2pinfo->noa_duration[i]);
808b1a3bfc9SLarry Finger 			rtl_write_dword(rtlpriv, 0x5E4,
809b1a3bfc9SLarry Finger 					p2pinfo->noa_interval[i]);
810b1a3bfc9SLarry Finger 
811b1a3bfc9SLarry Finger 			/*Get Current TSF value */
812b1a3bfc9SLarry Finger 			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
813b1a3bfc9SLarry Finger 
814b1a3bfc9SLarry Finger 			start_time = p2pinfo->noa_start_time[i];
815b1a3bfc9SLarry Finger 			if (p2pinfo->noa_count_type[i] != 1) {
816b1a3bfc9SLarry Finger 				while (start_time <= (tsf_low + (50 * 1024))) {
817b1a3bfc9SLarry Finger 					start_time += p2pinfo->noa_interval[i];
818b1a3bfc9SLarry Finger 					if (p2pinfo->noa_count_type[i] != 255)
819b1a3bfc9SLarry Finger 						p2pinfo->noa_count_type[i]--;
820b1a3bfc9SLarry Finger 				}
821b1a3bfc9SLarry Finger 			}
822b1a3bfc9SLarry Finger 			rtl_write_dword(rtlpriv, 0x5E8, start_time);
823b1a3bfc9SLarry Finger 			rtl_write_dword(rtlpriv, 0x5EC,
824b1a3bfc9SLarry Finger 					p2pinfo->noa_count_type[i]);
825b1a3bfc9SLarry Finger 		}
826b1a3bfc9SLarry Finger 		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
827b1a3bfc9SLarry Finger 			/* rst p2p circuit */
828b1a3bfc9SLarry Finger 			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
829b1a3bfc9SLarry Finger 			p2p_ps_offload->offload_en = 1;
830b1a3bfc9SLarry Finger 
831b1a3bfc9SLarry Finger 			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
832b1a3bfc9SLarry Finger 				p2p_ps_offload->role = 1;
833b1a3bfc9SLarry Finger 				p2p_ps_offload->allstasleep = 0;
834b1a3bfc9SLarry Finger 			} else {
835b1a3bfc9SLarry Finger 				p2p_ps_offload->role = 0;
836b1a3bfc9SLarry Finger 			}
837b1a3bfc9SLarry Finger 			p2p_ps_offload->discovery = 0;
838b1a3bfc9SLarry Finger 		}
839b1a3bfc9SLarry Finger 		break;
840b1a3bfc9SLarry Finger 	case P2P_PS_SCAN:
841e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
842b1a3bfc9SLarry Finger 		p2p_ps_offload->discovery = 1;
843b1a3bfc9SLarry Finger 		break;
844b1a3bfc9SLarry Finger 	case P2P_PS_SCAN_DONE:
845e24a2a87SLarry Finger 		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
846b1a3bfc9SLarry Finger 		p2p_ps_offload->discovery = 0;
847b1a3bfc9SLarry Finger 		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
848b1a3bfc9SLarry Finger 		break;
849b1a3bfc9SLarry Finger 	default:
850b1a3bfc9SLarry Finger 		break;
851b1a3bfc9SLarry Finger 	}
852b1a3bfc9SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
853b1a3bfc9SLarry Finger 			     (u8 *)p2p_ps_offload);
854b1a3bfc9SLarry Finger }
855b1a3bfc9SLarry Finger 
rtl92ee_c2h_ra_report_handler(struct ieee80211_hw * hw,u8 * cmd_buf,u8 cmd_len)85616cefa44SPing-Ke Shih void rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
857b1a3bfc9SLarry Finger 				   u8 *cmd_buf, u8 cmd_len)
858b1a3bfc9SLarry Finger {
859b1a3bfc9SLarry Finger 	u8 rate = cmd_buf[0] & 0x3F;
860b1a3bfc9SLarry Finger 	bool collision_state = cmd_buf[3] & BIT(0);
861b1a3bfc9SLarry Finger 
862b1a3bfc9SLarry Finger 	rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
863b1a3bfc9SLarry Finger }
864