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