1f1d2b4d3SLarry Finger /******************************************************************************
2f1d2b4d3SLarry Finger  *
3f1d2b4d3SLarry Finger  * Copyright(c) 2009-2012  Realtek Corporation.
4f1d2b4d3SLarry Finger  *
5f1d2b4d3SLarry Finger  * This program is free software; you can redistribute it and/or modify it
6f1d2b4d3SLarry Finger  * under the terms of version 2 of the GNU General Public License as
7f1d2b4d3SLarry Finger  * published by the Free Software Foundation.
8f1d2b4d3SLarry Finger  *
9f1d2b4d3SLarry Finger  * This program is distributed in the hope that it will be useful, but WITHOUT
10f1d2b4d3SLarry Finger  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11f1d2b4d3SLarry Finger  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12f1d2b4d3SLarry Finger  * more details.
13f1d2b4d3SLarry Finger  *
14f1d2b4d3SLarry Finger  * The full GNU General Public License is included in this distribution in the
15f1d2b4d3SLarry Finger  * file called LICENSE.
16f1d2b4d3SLarry Finger  *
17f1d2b4d3SLarry Finger  * Contact Information:
18f1d2b4d3SLarry Finger  * wlanfae <wlanfae@realtek.com>
19f1d2b4d3SLarry Finger  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20f1d2b4d3SLarry Finger  * Hsinchu 300, Taiwan.
21f1d2b4d3SLarry Finger  *
22f1d2b4d3SLarry Finger  * Larry Finger <Larry.Finger@lwfinger.net>
23f1d2b4d3SLarry Finger  *
24f1d2b4d3SLarry Finger  *****************************************************************************/
25f1d2b4d3SLarry Finger 
26f1d2b4d3SLarry Finger #include "../wifi.h"
27f1d2b4d3SLarry Finger #include "../pci.h"
28f1d2b4d3SLarry Finger #include "../base.h"
29f1d2b4d3SLarry Finger #include "../core.h"
30f1d2b4d3SLarry Finger #include "../rtl8192ce/reg.h"
31f1d2b4d3SLarry Finger #include "../rtl8192ce/def.h"
32f1d2b4d3SLarry Finger #include "fw_common.h"
33f1d2b4d3SLarry Finger #include <linux/export.h>
34f1d2b4d3SLarry Finger #include <linux/kmemleak.h>
35f1d2b4d3SLarry Finger 
36f1d2b4d3SLarry Finger static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
37f1d2b4d3SLarry Finger {
38f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
39f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
40f1d2b4d3SLarry Finger 
41f1d2b4d3SLarry Finger 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
42f1d2b4d3SLarry Finger 		u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
43f1d2b4d3SLarry Finger 		if (enable)
44f1d2b4d3SLarry Finger 			value32 |= MCUFWDL_EN;
45f1d2b4d3SLarry Finger 		else
46f1d2b4d3SLarry Finger 			value32 &= ~MCUFWDL_EN;
47f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
48f1d2b4d3SLarry Finger 	} else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
49f1d2b4d3SLarry Finger 		u8 tmp;
50f1d2b4d3SLarry Finger 		if (enable) {
51f1d2b4d3SLarry Finger 
52f1d2b4d3SLarry Finger 			tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
53f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
54f1d2b4d3SLarry Finger 				       tmp | 0x04);
55f1d2b4d3SLarry Finger 
56f1d2b4d3SLarry Finger 			tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
57f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
58f1d2b4d3SLarry Finger 
59f1d2b4d3SLarry Finger 			tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
60f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
61f1d2b4d3SLarry Finger 		} else {
62f1d2b4d3SLarry Finger 
63f1d2b4d3SLarry Finger 			tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
64f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
65f1d2b4d3SLarry Finger 
66f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
67f1d2b4d3SLarry Finger 		}
68f1d2b4d3SLarry Finger 	}
69f1d2b4d3SLarry Finger }
70f1d2b4d3SLarry Finger 
71f1d2b4d3SLarry Finger static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
72f1d2b4d3SLarry Finger 				   const u8 *buffer, u32 size)
73f1d2b4d3SLarry Finger {
74f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
75f1d2b4d3SLarry Finger 	u32 blocksize = sizeof(u32);
76f1d2b4d3SLarry Finger 	u8 *bufferptr = (u8 *)buffer;
77f1d2b4d3SLarry Finger 	u32 *pu4byteptr = (u32 *)buffer;
78f1d2b4d3SLarry Finger 	u32 i, offset, blockcount, remainsize;
79f1d2b4d3SLarry Finger 
80f1d2b4d3SLarry Finger 	blockcount = size / blocksize;
81f1d2b4d3SLarry Finger 	remainsize = size % blocksize;
82f1d2b4d3SLarry Finger 
83f1d2b4d3SLarry Finger 	for (i = 0; i < blockcount; i++) {
84f1d2b4d3SLarry Finger 		offset = i * blocksize;
85f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
86f1d2b4d3SLarry Finger 				*(pu4byteptr + i));
87f1d2b4d3SLarry Finger 	}
88f1d2b4d3SLarry Finger 
89f1d2b4d3SLarry Finger 	if (remainsize) {
90f1d2b4d3SLarry Finger 		offset = blockcount * blocksize;
91f1d2b4d3SLarry Finger 		bufferptr += offset;
92f1d2b4d3SLarry Finger 		for (i = 0; i < remainsize; i++) {
93f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
94f1d2b4d3SLarry Finger 						 offset + i), *(bufferptr + i));
95f1d2b4d3SLarry Finger 		}
96f1d2b4d3SLarry Finger 	}
97f1d2b4d3SLarry Finger }
98f1d2b4d3SLarry Finger 
99f1d2b4d3SLarry Finger static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
100f1d2b4d3SLarry Finger 				  u32 page, const u8 *buffer, u32 size)
101f1d2b4d3SLarry Finger {
102f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
103f1d2b4d3SLarry Finger 	u8 value8;
104f1d2b4d3SLarry Finger 	u8 u8page = (u8) (page & 0x07);
105f1d2b4d3SLarry Finger 
106f1d2b4d3SLarry Finger 	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
107f1d2b4d3SLarry Finger 
108f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
109f1d2b4d3SLarry Finger 	_rtl92c_fw_block_write(hw, buffer, size);
110f1d2b4d3SLarry Finger }
111f1d2b4d3SLarry Finger 
112f1d2b4d3SLarry Finger static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
113f1d2b4d3SLarry Finger {
114f1d2b4d3SLarry Finger 	u32 fwlen = *pfwlen;
115f1d2b4d3SLarry Finger 	u8 remain = (u8) (fwlen % 4);
116f1d2b4d3SLarry Finger 
117f1d2b4d3SLarry Finger 	remain = (remain == 0) ? 0 : (4 - remain);
118f1d2b4d3SLarry Finger 
119f1d2b4d3SLarry Finger 	while (remain > 0) {
120f1d2b4d3SLarry Finger 		pfwbuf[fwlen] = 0;
121f1d2b4d3SLarry Finger 		fwlen++;
122f1d2b4d3SLarry Finger 		remain--;
123f1d2b4d3SLarry Finger 	}
124f1d2b4d3SLarry Finger 
125f1d2b4d3SLarry Finger 	*pfwlen = fwlen;
126f1d2b4d3SLarry Finger }
127f1d2b4d3SLarry Finger 
128f1d2b4d3SLarry Finger static void _rtl92c_write_fw(struct ieee80211_hw *hw,
129f1d2b4d3SLarry Finger 			     enum version_8192c version, u8 *buffer, u32 size)
130f1d2b4d3SLarry Finger {
131f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
132f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
133f1d2b4d3SLarry Finger 	bool is_version_b;
134f1d2b4d3SLarry Finger 	u8 *bufferptr = (u8 *)buffer;
135f1d2b4d3SLarry Finger 
136f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
137f1d2b4d3SLarry Finger 	is_version_b = IS_NORMAL_CHIP(version);
138f1d2b4d3SLarry Finger 	if (is_version_b) {
139f1d2b4d3SLarry Finger 		u32 pageNums, remainsize;
140f1d2b4d3SLarry Finger 		u32 page, offset;
141f1d2b4d3SLarry Finger 
142f1d2b4d3SLarry Finger 		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
143f1d2b4d3SLarry Finger 			_rtl92c_fill_dummy(bufferptr, &size);
144f1d2b4d3SLarry Finger 
145f1d2b4d3SLarry Finger 		pageNums = size / FW_8192C_PAGE_SIZE;
146f1d2b4d3SLarry Finger 		remainsize = size % FW_8192C_PAGE_SIZE;
147f1d2b4d3SLarry Finger 
1480fc30e93SLarry Finger 		if (pageNums > 4)
1490fc30e93SLarry Finger 			pr_err("Page numbers should not greater then 4\n");
150f1d2b4d3SLarry Finger 
151f1d2b4d3SLarry Finger 		for (page = 0; page < pageNums; page++) {
152f1d2b4d3SLarry Finger 			offset = page * FW_8192C_PAGE_SIZE;
153f1d2b4d3SLarry Finger 			_rtl92c_fw_page_write(hw, page, (bufferptr + offset),
154f1d2b4d3SLarry Finger 					      FW_8192C_PAGE_SIZE);
155f1d2b4d3SLarry Finger 		}
156f1d2b4d3SLarry Finger 
157f1d2b4d3SLarry Finger 		if (remainsize) {
158f1d2b4d3SLarry Finger 			offset = pageNums * FW_8192C_PAGE_SIZE;
159f1d2b4d3SLarry Finger 			page = pageNums;
160f1d2b4d3SLarry Finger 			_rtl92c_fw_page_write(hw, page, (bufferptr + offset),
161f1d2b4d3SLarry Finger 					      remainsize);
162f1d2b4d3SLarry Finger 		}
163f1d2b4d3SLarry Finger 	} else {
164f1d2b4d3SLarry Finger 		_rtl92c_fw_block_write(hw, buffer, size);
165f1d2b4d3SLarry Finger 	}
166f1d2b4d3SLarry Finger }
167f1d2b4d3SLarry Finger 
168f1d2b4d3SLarry Finger static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
169f1d2b4d3SLarry Finger {
170f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
171f1d2b4d3SLarry Finger 	int err = -EIO;
172f1d2b4d3SLarry Finger 	u32 counter = 0;
173f1d2b4d3SLarry Finger 	u32 value32;
174f1d2b4d3SLarry Finger 
175f1d2b4d3SLarry Finger 	do {
176f1d2b4d3SLarry Finger 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
177f1d2b4d3SLarry Finger 	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
178f1d2b4d3SLarry Finger 		 (!(value32 & FWDL_ChkSum_rpt)));
179f1d2b4d3SLarry Finger 
180f1d2b4d3SLarry Finger 	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
1810fc30e93SLarry Finger 		pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n",
182f1d2b4d3SLarry Finger 		       value32);
183f1d2b4d3SLarry Finger 		goto exit;
184f1d2b4d3SLarry Finger 	}
185f1d2b4d3SLarry Finger 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
186f1d2b4d3SLarry Finger 	value32 |= MCUFWDL_RDY;
187f1d2b4d3SLarry Finger 	value32 &= ~WINTINI_RDY;
188f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
189f1d2b4d3SLarry Finger 
190f1d2b4d3SLarry Finger 	counter = 0;
191f1d2b4d3SLarry Finger 
192f1d2b4d3SLarry Finger 	do {
193f1d2b4d3SLarry Finger 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
1940fc30e93SLarry Finger 		if (value32 & WINTINI_RDY)
1950fc30e93SLarry Finger 			return 0;
196f1d2b4d3SLarry Finger 
197f1d2b4d3SLarry Finger 		mdelay(FW_8192C_POLLING_DELAY);
198f1d2b4d3SLarry Finger 
199f1d2b4d3SLarry Finger 	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
200f1d2b4d3SLarry Finger 
2010fc30e93SLarry Finger 	pr_err("Polling FW ready fail! REG_MCUFWDL:0x%08x.\n",
2020fc30e93SLarry Finger 	       value32);
203f1d2b4d3SLarry Finger 
204f1d2b4d3SLarry Finger exit:
205f1d2b4d3SLarry Finger 	return err;
206f1d2b4d3SLarry Finger }
207f1d2b4d3SLarry Finger 
208f1d2b4d3SLarry Finger int rtl92c_download_fw(struct ieee80211_hw *hw)
209f1d2b4d3SLarry Finger {
210f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
211f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
212f1d2b4d3SLarry Finger 	struct rtlwifi_firmware_header *pfwheader;
213f1d2b4d3SLarry Finger 	u8 *pfwdata;
214f1d2b4d3SLarry Finger 	u32 fwsize;
215f1d2b4d3SLarry Finger 	int err;
216f1d2b4d3SLarry Finger 	enum version_8192c version = rtlhal->version;
217f1d2b4d3SLarry Finger 
218f1d2b4d3SLarry Finger 	if (!rtlhal->pfirmware)
219f1d2b4d3SLarry Finger 		return 1;
220f1d2b4d3SLarry Finger 
221f1d2b4d3SLarry Finger 	pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
222f1d2b4d3SLarry Finger 	pfwdata = (u8 *)rtlhal->pfirmware;
223f1d2b4d3SLarry Finger 	fwsize = rtlhal->fwsize;
224f1d2b4d3SLarry Finger 	if (IS_FW_HEADER_EXIST(pfwheader)) {
225f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
226f1d2b4d3SLarry Finger 			 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
227f1d2b4d3SLarry Finger 			  pfwheader->version, pfwheader->signature,
228f1d2b4d3SLarry Finger 			  (int)sizeof(struct rtlwifi_firmware_header));
229f1d2b4d3SLarry Finger 
230f1d2b4d3SLarry Finger 		rtlhal->fw_version = le16_to_cpu(pfwheader->version);
231f1d2b4d3SLarry Finger 		rtlhal->fw_subversion = pfwheader->subversion;
232f1d2b4d3SLarry Finger 		pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
233f1d2b4d3SLarry Finger 		fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
234f1d2b4d3SLarry Finger 	}
235f1d2b4d3SLarry Finger 
236f1d2b4d3SLarry Finger 	_rtl92c_enable_fw_download(hw, true);
237f1d2b4d3SLarry Finger 	_rtl92c_write_fw(hw, version, pfwdata, fwsize);
238f1d2b4d3SLarry Finger 	_rtl92c_enable_fw_download(hw, false);
239f1d2b4d3SLarry Finger 
240f1d2b4d3SLarry Finger 	err = _rtl92c_fw_free_to_go(hw);
241f1d2b4d3SLarry Finger 	if (err) {
2420fc30e93SLarry Finger 		pr_err("Firmware is not ready to run!\n");
243f1d2b4d3SLarry Finger 	} else {
244f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
245f1d2b4d3SLarry Finger 			 "Firmware is ready to run!\n");
246f1d2b4d3SLarry Finger 	}
247f1d2b4d3SLarry Finger 
248f1d2b4d3SLarry Finger 	return 0;
249f1d2b4d3SLarry Finger }
250f1d2b4d3SLarry Finger EXPORT_SYMBOL(rtl92c_download_fw);
251f1d2b4d3SLarry Finger 
252f1d2b4d3SLarry Finger static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
253f1d2b4d3SLarry Finger {
254f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
255f1d2b4d3SLarry Finger 	u8 val_hmetfr, val_mcutst_1;
256f1d2b4d3SLarry Finger 	bool result = false;
257f1d2b4d3SLarry Finger 
258f1d2b4d3SLarry Finger 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
259f1d2b4d3SLarry Finger 	val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
260f1d2b4d3SLarry Finger 
261f1d2b4d3SLarry Finger 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
262f1d2b4d3SLarry Finger 		result = true;
263f1d2b4d3SLarry Finger 	return result;
264f1d2b4d3SLarry Finger }
265f1d2b4d3SLarry Finger 
266f1d2b4d3SLarry Finger static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
267f1d2b4d3SLarry Finger 			      u8 element_id, u32 cmd_len, u8 *cmdbuffer)
268f1d2b4d3SLarry Finger {
269f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
270f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
271f1d2b4d3SLarry Finger 	u8 boxnum;
272f1d2b4d3SLarry Finger 	u16 box_reg = 0, box_extreg = 0;
273f1d2b4d3SLarry Finger 	u8 u1b_tmp;
274f1d2b4d3SLarry Finger 	bool isfw_read = false;
275f1d2b4d3SLarry Finger 	u8 buf_index = 0;
276f1d2b4d3SLarry Finger 	bool bwrite_sucess = false;
277f1d2b4d3SLarry Finger 	u8 wait_h2c_limmit = 100;
278f1d2b4d3SLarry Finger 	u8 wait_writeh2c_limmit = 100;
279f1d2b4d3SLarry Finger 	u8 boxcontent[4], boxextcontent[2];
280f1d2b4d3SLarry Finger 	u32 h2c_waitcounter = 0;
281f1d2b4d3SLarry Finger 	unsigned long flag;
282f1d2b4d3SLarry Finger 	u8 idx;
283f1d2b4d3SLarry Finger 
284f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
285f1d2b4d3SLarry Finger 
286f1d2b4d3SLarry Finger 	while (true) {
287f1d2b4d3SLarry Finger 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
288f1d2b4d3SLarry Finger 		if (rtlhal->h2c_setinprogress) {
289f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
290f1d2b4d3SLarry Finger 				 "H2C set in progress! Wait to set..element_id(%d).\n",
291f1d2b4d3SLarry Finger 				 element_id);
292f1d2b4d3SLarry Finger 			while (rtlhal->h2c_setinprogress) {
293f1d2b4d3SLarry Finger 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
294f1d2b4d3SLarry Finger 						       flag);
295f1d2b4d3SLarry Finger 				h2c_waitcounter++;
296f1d2b4d3SLarry Finger 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
297f1d2b4d3SLarry Finger 					 "Wait 100 us (%d times)...\n",
298f1d2b4d3SLarry Finger 					  h2c_waitcounter);
299f1d2b4d3SLarry Finger 				udelay(100);
300f1d2b4d3SLarry Finger 
301f1d2b4d3SLarry Finger 				if (h2c_waitcounter > 1000)
302f1d2b4d3SLarry Finger 					return;
303f1d2b4d3SLarry Finger 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
304f1d2b4d3SLarry Finger 						  flag);
305f1d2b4d3SLarry Finger 			}
306f1d2b4d3SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
307f1d2b4d3SLarry Finger 		} else {
308f1d2b4d3SLarry Finger 			rtlhal->h2c_setinprogress = true;
309f1d2b4d3SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
310f1d2b4d3SLarry Finger 			break;
311f1d2b4d3SLarry Finger 		}
312f1d2b4d3SLarry Finger 	}
313f1d2b4d3SLarry Finger 
314f1d2b4d3SLarry Finger 	while (!bwrite_sucess) {
315f1d2b4d3SLarry Finger 		wait_writeh2c_limmit--;
316f1d2b4d3SLarry Finger 		if (wait_writeh2c_limmit == 0) {
3170fc30e93SLarry Finger 			pr_err("Write H2C fail because no trigger for FW INT!\n");
318f1d2b4d3SLarry Finger 			break;
319f1d2b4d3SLarry Finger 		}
320f1d2b4d3SLarry Finger 
321f1d2b4d3SLarry Finger 		boxnum = rtlhal->last_hmeboxnum;
322f1d2b4d3SLarry Finger 		switch (boxnum) {
323f1d2b4d3SLarry Finger 		case 0:
324f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_0;
325f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_0;
326f1d2b4d3SLarry Finger 			break;
327f1d2b4d3SLarry Finger 		case 1:
328f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_1;
329f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_1;
330f1d2b4d3SLarry Finger 			break;
331f1d2b4d3SLarry Finger 		case 2:
332f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_2;
333f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_2;
334f1d2b4d3SLarry Finger 			break;
335f1d2b4d3SLarry Finger 		case 3:
336f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_3;
337f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_3;
338f1d2b4d3SLarry Finger 			break;
339f1d2b4d3SLarry Finger 		default:
340f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
341ad574889SJoe Perches 				 "switch case %#x not processed\n", boxnum);
342f1d2b4d3SLarry Finger 			break;
343f1d2b4d3SLarry Finger 		}
344f1d2b4d3SLarry Finger 
345f1d2b4d3SLarry Finger 		isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
346f1d2b4d3SLarry Finger 		while (!isfw_read) {
347f1d2b4d3SLarry Finger 			wait_h2c_limmit--;
348f1d2b4d3SLarry Finger 			if (wait_h2c_limmit == 0) {
349f1d2b4d3SLarry Finger 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
350f1d2b4d3SLarry Finger 					 "Waiting too long for FW read clear HMEBox(%d)!\n",
351f1d2b4d3SLarry Finger 					 boxnum);
352f1d2b4d3SLarry Finger 				break;
353f1d2b4d3SLarry Finger 			}
354f1d2b4d3SLarry Finger 
355f1d2b4d3SLarry Finger 			udelay(10);
356f1d2b4d3SLarry Finger 
357f1d2b4d3SLarry Finger 			isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
358f1d2b4d3SLarry Finger 			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
359f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
360f1d2b4d3SLarry Finger 				 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
361f1d2b4d3SLarry Finger 				 boxnum, u1b_tmp);
362f1d2b4d3SLarry Finger 		}
363f1d2b4d3SLarry Finger 
364f1d2b4d3SLarry Finger 		if (!isfw_read) {
365f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
366f1d2b4d3SLarry Finger 				 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
367f1d2b4d3SLarry Finger 				 boxnum);
368f1d2b4d3SLarry Finger 			break;
369f1d2b4d3SLarry Finger 		}
370f1d2b4d3SLarry Finger 
371f1d2b4d3SLarry Finger 		memset(boxcontent, 0, sizeof(boxcontent));
372f1d2b4d3SLarry Finger 		memset(boxextcontent, 0, sizeof(boxextcontent));
373f1d2b4d3SLarry Finger 		boxcontent[0] = element_id;
374f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
375f1d2b4d3SLarry Finger 			 "Write element_id box_reg(%4x) = %2x\n",
376f1d2b4d3SLarry Finger 			  box_reg, element_id);
377f1d2b4d3SLarry Finger 
378f1d2b4d3SLarry Finger 		switch (cmd_len) {
379f1d2b4d3SLarry Finger 		case 1:
380f1d2b4d3SLarry Finger 			boxcontent[0] &= ~(BIT(7));
381f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
382f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index, 1);
383f1d2b4d3SLarry Finger 
384f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
385f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
386f1d2b4d3SLarry Finger 					       boxcontent[idx]);
387f1d2b4d3SLarry Finger 			}
388f1d2b4d3SLarry Finger 			break;
389f1d2b4d3SLarry Finger 		case 2:
390f1d2b4d3SLarry Finger 			boxcontent[0] &= ~(BIT(7));
391f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
392f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index, 2);
393f1d2b4d3SLarry Finger 
394f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
395f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
396f1d2b4d3SLarry Finger 					       boxcontent[idx]);
397f1d2b4d3SLarry Finger 			}
398f1d2b4d3SLarry Finger 			break;
399f1d2b4d3SLarry Finger 		case 3:
400f1d2b4d3SLarry Finger 			boxcontent[0] &= ~(BIT(7));
401f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
402f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index, 3);
403f1d2b4d3SLarry Finger 
404f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
405f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
406f1d2b4d3SLarry Finger 					       boxcontent[idx]);
407f1d2b4d3SLarry Finger 			}
408f1d2b4d3SLarry Finger 			break;
409f1d2b4d3SLarry Finger 		case 4:
410f1d2b4d3SLarry Finger 			boxcontent[0] |= (BIT(7));
411f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxextcontent),
412f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index, 2);
413f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
414f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index + 2, 2);
415f1d2b4d3SLarry Finger 
416f1d2b4d3SLarry Finger 			for (idx = 0; idx < 2; idx++) {
417f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_extreg + idx,
418f1d2b4d3SLarry Finger 					       boxextcontent[idx]);
419f1d2b4d3SLarry Finger 			}
420f1d2b4d3SLarry Finger 
421f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
422f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
423f1d2b4d3SLarry Finger 					       boxcontent[idx]);
424f1d2b4d3SLarry Finger 			}
425f1d2b4d3SLarry Finger 			break;
426f1d2b4d3SLarry Finger 		case 5:
427f1d2b4d3SLarry Finger 			boxcontent[0] |= (BIT(7));
428f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxextcontent),
429f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index, 2);
430f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
431f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index + 2, 3);
432f1d2b4d3SLarry Finger 
433f1d2b4d3SLarry Finger 			for (idx = 0; idx < 2; idx++) {
434f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_extreg + idx,
435f1d2b4d3SLarry Finger 					       boxextcontent[idx]);
436f1d2b4d3SLarry Finger 			}
437f1d2b4d3SLarry Finger 
438f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
439f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
440f1d2b4d3SLarry Finger 					       boxcontent[idx]);
441f1d2b4d3SLarry Finger 			}
442f1d2b4d3SLarry Finger 			break;
443f1d2b4d3SLarry Finger 		default:
444f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
445ad574889SJoe Perches 				 "switch case %#x not processed\n", cmd_len);
446f1d2b4d3SLarry Finger 			break;
447f1d2b4d3SLarry Finger 		}
448f1d2b4d3SLarry Finger 
449f1d2b4d3SLarry Finger 		bwrite_sucess = true;
450f1d2b4d3SLarry Finger 
451f1d2b4d3SLarry Finger 		rtlhal->last_hmeboxnum = boxnum + 1;
452f1d2b4d3SLarry Finger 		if (rtlhal->last_hmeboxnum == 4)
453f1d2b4d3SLarry Finger 			rtlhal->last_hmeboxnum = 0;
454f1d2b4d3SLarry Finger 
455f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
456f1d2b4d3SLarry Finger 			 "pHalData->last_hmeboxnum  = %d\n",
457f1d2b4d3SLarry Finger 			  rtlhal->last_hmeboxnum);
458f1d2b4d3SLarry Finger 	}
459f1d2b4d3SLarry Finger 
460f1d2b4d3SLarry Finger 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
461f1d2b4d3SLarry Finger 	rtlhal->h2c_setinprogress = false;
462f1d2b4d3SLarry Finger 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
463f1d2b4d3SLarry Finger 
464f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
465f1d2b4d3SLarry Finger }
466f1d2b4d3SLarry Finger 
467f1d2b4d3SLarry Finger void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
468f1d2b4d3SLarry Finger 			 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
469f1d2b4d3SLarry Finger {
470f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
471f1d2b4d3SLarry Finger 	u32 tmp_cmdbuf[2];
472f1d2b4d3SLarry Finger 
473f1d2b4d3SLarry Finger 	if (!rtlhal->fw_ready) {
474531940f9SLarry Finger 		WARN_ONCE(true,
475531940f9SLarry Finger 			  "rtl8192c-common: return H2C cmd because of Fw download fail!!!\n");
476f1d2b4d3SLarry Finger 		return;
477f1d2b4d3SLarry Finger 	}
478f1d2b4d3SLarry Finger 
479f1d2b4d3SLarry Finger 	memset(tmp_cmdbuf, 0, 8);
480f1d2b4d3SLarry Finger 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
481f1d2b4d3SLarry Finger 	_rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
482f1d2b4d3SLarry Finger 
483f1d2b4d3SLarry Finger 	return;
484f1d2b4d3SLarry Finger }
485f1d2b4d3SLarry Finger EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
486f1d2b4d3SLarry Finger 
487f1d2b4d3SLarry Finger void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
488f1d2b4d3SLarry Finger {
489f1d2b4d3SLarry Finger 	u8 u1b_tmp;
490f1d2b4d3SLarry Finger 	u8 delay = 100;
491f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
492f1d2b4d3SLarry Finger 
493f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
494f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
495f1d2b4d3SLarry Finger 
496f1d2b4d3SLarry Finger 	while (u1b_tmp & BIT(2)) {
497f1d2b4d3SLarry Finger 		delay--;
498f1d2b4d3SLarry Finger 		if (delay == 0) {
499531940f9SLarry Finger 			WARN_ONCE(true, "rtl8192c-common: 8051 reset fail.\n");
500f1d2b4d3SLarry Finger 			break;
501f1d2b4d3SLarry Finger 		}
502f1d2b4d3SLarry Finger 		udelay(50);
503f1d2b4d3SLarry Finger 		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
504f1d2b4d3SLarry Finger 	}
505f1d2b4d3SLarry Finger }
506f1d2b4d3SLarry Finger EXPORT_SYMBOL(rtl92c_firmware_selfreset);
507f1d2b4d3SLarry Finger 
508f1d2b4d3SLarry Finger void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
509f1d2b4d3SLarry Finger {
510f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
511f1d2b4d3SLarry Finger 	u8 u1_h2c_set_pwrmode[3] = { 0 };
512f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
513f1d2b4d3SLarry Finger 
514f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
515f1d2b4d3SLarry Finger 
516f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
517f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
518f1d2b4d3SLarry Finger 		(rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
519f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
520f1d2b4d3SLarry Finger 					      ppsc->reg_max_lps_awakeintvl);
521f1d2b4d3SLarry Finger 
522f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
523f1d2b4d3SLarry Finger 		      "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
524f1d2b4d3SLarry Finger 		      u1_h2c_set_pwrmode, 3);
525f1d2b4d3SLarry Finger 	rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
526f1d2b4d3SLarry Finger }
527f1d2b4d3SLarry Finger EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
528f1d2b4d3SLarry Finger 
529f1d2b4d3SLarry Finger #define BEACON_PG		0 /*->1*/
530f1d2b4d3SLarry Finger #define PSPOLL_PG		2
531f1d2b4d3SLarry Finger #define NULL_PG			3
532f1d2b4d3SLarry Finger #define PROBERSP_PG		4 /*->5*/
533f1d2b4d3SLarry Finger 
534f1d2b4d3SLarry Finger #define TOTAL_RESERVED_PKT_LEN	768
535f1d2b4d3SLarry Finger 
536f1d2b4d3SLarry Finger static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
537f1d2b4d3SLarry Finger 	/* page 0 beacon */
538f1d2b4d3SLarry Finger 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
539f1d2b4d3SLarry Finger 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
540f1d2b4d3SLarry Finger 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
541f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542f1d2b4d3SLarry Finger 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
543f1d2b4d3SLarry Finger 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
544f1d2b4d3SLarry Finger 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
545f1d2b4d3SLarry Finger 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
546f1d2b4d3SLarry Finger 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
547f1d2b4d3SLarry Finger 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
548f1d2b4d3SLarry Finger 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551f1d2b4d3SLarry Finger 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
552f1d2b4d3SLarry Finger 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554f1d2b4d3SLarry Finger 
555f1d2b4d3SLarry Finger 	/* page 1 beacon */
556f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568f1d2b4d3SLarry Finger 	0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
569f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570f1d2b4d3SLarry Finger 	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572f1d2b4d3SLarry Finger 
573f1d2b4d3SLarry Finger 	/* page 2  ps-poll */
574f1d2b4d3SLarry Finger 	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
575f1d2b4d3SLarry Finger 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
576f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586f1d2b4d3SLarry Finger 	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
587f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
588f1d2b4d3SLarry Finger 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590f1d2b4d3SLarry Finger 
591f1d2b4d3SLarry Finger 	/* page 3  null */
592f1d2b4d3SLarry Finger 	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
593f1d2b4d3SLarry Finger 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
594f1d2b4d3SLarry Finger 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
595f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601f1d2b4d3SLarry Finger 	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 	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
605f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
606f1d2b4d3SLarry Finger 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608f1d2b4d3SLarry Finger 
609f1d2b4d3SLarry Finger 	/* page 4  probe_resp */
610f1d2b4d3SLarry Finger 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
611f1d2b4d3SLarry Finger 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
612f1d2b4d3SLarry Finger 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
613f1d2b4d3SLarry Finger 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
614f1d2b4d3SLarry Finger 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
615f1d2b4d3SLarry Finger 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
616f1d2b4d3SLarry Finger 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
617f1d2b4d3SLarry Finger 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
618f1d2b4d3SLarry Finger 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
619f1d2b4d3SLarry Finger 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
620f1d2b4d3SLarry Finger 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623f1d2b4d3SLarry Finger 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
624f1d2b4d3SLarry Finger 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626f1d2b4d3SLarry Finger 
627f1d2b4d3SLarry Finger 	/* page 5  probe_resp */
628f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644f1d2b4d3SLarry Finger };
645f1d2b4d3SLarry Finger 
646f1d2b4d3SLarry Finger void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
647f1d2b4d3SLarry Finger 	 bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *))
648f1d2b4d3SLarry Finger {
649f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
650f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
651f1d2b4d3SLarry Finger 	struct sk_buff *skb = NULL;
652f1d2b4d3SLarry Finger 
653f1d2b4d3SLarry Finger 	u32 totalpacketlen;
654f1d2b4d3SLarry Finger 	bool rtstatus;
655f1d2b4d3SLarry Finger 	u8 u1rsvdpageloc[3] = { 0 };
656f1d2b4d3SLarry Finger 	bool b_dlok = false;
657f1d2b4d3SLarry Finger 
658f1d2b4d3SLarry Finger 	u8 *beacon;
659f1d2b4d3SLarry Finger 	u8 *p_pspoll;
660f1d2b4d3SLarry Finger 	u8 *nullfunc;
661f1d2b4d3SLarry Finger 	u8 *p_probersp;
662f1d2b4d3SLarry Finger 	/*---------------------------------------------------------
663f1d2b4d3SLarry Finger 				(1) beacon
664f1d2b4d3SLarry Finger 	---------------------------------------------------------*/
665f1d2b4d3SLarry Finger 	beacon = &reserved_page_packet[BEACON_PG * 128];
666f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
667f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
668f1d2b4d3SLarry Finger 
669f1d2b4d3SLarry Finger 	/*-------------------------------------------------------
670f1d2b4d3SLarry Finger 				(2) ps-poll
671f1d2b4d3SLarry Finger 	--------------------------------------------------------*/
672f1d2b4d3SLarry Finger 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
673f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
674f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
675f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
676f1d2b4d3SLarry Finger 
677f1d2b4d3SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
678f1d2b4d3SLarry Finger 
679f1d2b4d3SLarry Finger 	/*--------------------------------------------------------
680f1d2b4d3SLarry Finger 				(3) null data
681f1d2b4d3SLarry Finger 	---------------------------------------------------------*/
682f1d2b4d3SLarry Finger 	nullfunc = &reserved_page_packet[NULL_PG * 128];
683f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
684f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
685f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
686f1d2b4d3SLarry Finger 
687f1d2b4d3SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
688f1d2b4d3SLarry Finger 
689f1d2b4d3SLarry Finger 	/*---------------------------------------------------------
690f1d2b4d3SLarry Finger 				(4) probe response
691f1d2b4d3SLarry Finger 	----------------------------------------------------------*/
692f1d2b4d3SLarry Finger 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
693f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
694f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
695f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
696f1d2b4d3SLarry Finger 
697f1d2b4d3SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
698f1d2b4d3SLarry Finger 
699f1d2b4d3SLarry Finger 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
700f1d2b4d3SLarry Finger 
701f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
702f1d2b4d3SLarry Finger 		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
703f1d2b4d3SLarry Finger 		      &reserved_page_packet[0], totalpacketlen);
704f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
705f1d2b4d3SLarry Finger 		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
706f1d2b4d3SLarry Finger 		      u1rsvdpageloc, 3);
707f1d2b4d3SLarry Finger 
708f1d2b4d3SLarry Finger 
709f1d2b4d3SLarry Finger 	skb = dev_alloc_skb(totalpacketlen);
710f1d2b4d3SLarry Finger 	memcpy((u8 *)skb_put(skb, totalpacketlen),
711f1d2b4d3SLarry Finger 	       &reserved_page_packet, totalpacketlen);
712f1d2b4d3SLarry Finger 
713f1d2b4d3SLarry Finger 	if (cmd_send_packet)
714f1d2b4d3SLarry Finger 		rtstatus = cmd_send_packet(hw, skb);
715f1d2b4d3SLarry Finger 	else
716f1d2b4d3SLarry Finger 		rtstatus = rtl_cmd_send_packet(hw, skb);
717f1d2b4d3SLarry Finger 
718f1d2b4d3SLarry Finger 	if (rtstatus)
719f1d2b4d3SLarry Finger 		b_dlok = true;
720f1d2b4d3SLarry Finger 
721f1d2b4d3SLarry Finger 	if (b_dlok) {
722f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
723f1d2b4d3SLarry Finger 			 "Set RSVD page location to Fw.\n");
724f1d2b4d3SLarry Finger 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
725f1d2b4d3SLarry Finger 				"H2C_RSVDPAGE:\n",
726f1d2b4d3SLarry Finger 				u1rsvdpageloc, 3);
727f1d2b4d3SLarry Finger 		rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
728f1d2b4d3SLarry Finger 				    sizeof(u1rsvdpageloc), u1rsvdpageloc);
729f1d2b4d3SLarry Finger 	} else
730f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
731f1d2b4d3SLarry Finger 			 "Set RSVD page location to Fw FAIL!!!!!!.\n");
732f1d2b4d3SLarry Finger }
733f1d2b4d3SLarry Finger EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
734f1d2b4d3SLarry Finger 
735f1d2b4d3SLarry Finger void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
736f1d2b4d3SLarry Finger {
737f1d2b4d3SLarry Finger 	u8 u1_joinbssrpt_parm[1] = { 0 };
738f1d2b4d3SLarry Finger 
739f1d2b4d3SLarry Finger 	SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
740f1d2b4d3SLarry Finger 
741f1d2b4d3SLarry Finger 	rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
742f1d2b4d3SLarry Finger }
743f1d2b4d3SLarry Finger EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);
744f1d2b4d3SLarry Finger 
745f1d2b4d3SLarry Finger static void rtl92c_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
746f1d2b4d3SLarry Finger {
747f1d2b4d3SLarry Finger 	u8 u1_ctwindow_period[1] = { ctwindow};
748f1d2b4d3SLarry Finger 
749f1d2b4d3SLarry Finger 	rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
750f1d2b4d3SLarry Finger }
751f1d2b4d3SLarry Finger 
752f1d2b4d3SLarry Finger /* refactored routine */
753f1d2b4d3SLarry Finger static void set_noa_data(struct rtl_priv *rtlpriv,
754f1d2b4d3SLarry Finger 			 struct rtl_p2p_ps_info *p2pinfo,
755f1d2b4d3SLarry Finger 			 struct p2p_ps_offload_t *p2p_ps_offload)
756f1d2b4d3SLarry Finger {
757f1d2b4d3SLarry Finger 	int i;
758f1d2b4d3SLarry Finger 	u32	start_time, tsf_low;
759f1d2b4d3SLarry Finger 
760f1d2b4d3SLarry Finger 	/* hw only support 2 set of NoA */
761f1d2b4d3SLarry Finger 	for (i = 0 ; i < p2pinfo->noa_num ; i++) {
762f1d2b4d3SLarry Finger 		/* To control the reg setting for which NOA*/
763f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
764f1d2b4d3SLarry Finger 		if (i == 0)
765f1d2b4d3SLarry Finger 			p2p_ps_offload->noa0_en = 1;
766f1d2b4d3SLarry Finger 		else
767f1d2b4d3SLarry Finger 			p2p_ps_offload->noa1_en = 1;
768f1d2b4d3SLarry Finger 
769f1d2b4d3SLarry Finger 		/* config P2P NoA Descriptor Register */
770f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, 0x5E0,
771f1d2b4d3SLarry Finger 				p2pinfo->noa_duration[i]);
772f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, 0x5E4,
773f1d2b4d3SLarry Finger 				p2pinfo->noa_interval[i]);
774f1d2b4d3SLarry Finger 
775f1d2b4d3SLarry Finger 		/*Get Current TSF value */
776f1d2b4d3SLarry Finger 		tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
777f1d2b4d3SLarry Finger 
778f1d2b4d3SLarry Finger 		start_time = p2pinfo->noa_start_time[i];
779f1d2b4d3SLarry Finger 		if (p2pinfo->noa_count_type[i] != 1) {
780f1d2b4d3SLarry Finger 			while (start_time <= (tsf_low+(50*1024))) {
781f1d2b4d3SLarry Finger 				start_time += p2pinfo->noa_interval[i];
782f1d2b4d3SLarry Finger 				if (p2pinfo->noa_count_type[i] != 255)
783f1d2b4d3SLarry Finger 					p2pinfo->noa_count_type[i]--;
784f1d2b4d3SLarry Finger 			}
785f1d2b4d3SLarry Finger 		}
786f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, 0x5E8, start_time);
787f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, 0x5EC,
788f1d2b4d3SLarry Finger 				p2pinfo->noa_count_type[i]);
789f1d2b4d3SLarry Finger 	}
790f1d2b4d3SLarry Finger }
791f1d2b4d3SLarry Finger 
792f1d2b4d3SLarry Finger void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
793f1d2b4d3SLarry Finger {
794f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
795f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
796f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
797f1d2b4d3SLarry Finger 	struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
798f1d2b4d3SLarry Finger 	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
799f1d2b4d3SLarry Finger 	u16	ctwindow;
800f1d2b4d3SLarry Finger 
801f1d2b4d3SLarry Finger 	switch (p2p_ps_state) {
802f1d2b4d3SLarry Finger 	case P2P_PS_DISABLE:
803f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
804f1d2b4d3SLarry Finger 				 "P2P_PS_DISABLE\n");
805f1d2b4d3SLarry Finger 			memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
806f1d2b4d3SLarry Finger 			break;
807f1d2b4d3SLarry Finger 	case P2P_PS_ENABLE:
808f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
809f1d2b4d3SLarry Finger 				 "P2P_PS_ENABLE\n");
810f1d2b4d3SLarry Finger 			/* update CTWindow value. */
811f1d2b4d3SLarry Finger 			if (p2pinfo->ctwindow > 0) {
812f1d2b4d3SLarry Finger 				p2p_ps_offload->ctwindow_en = 1;
813f1d2b4d3SLarry Finger 				ctwindow = p2pinfo->ctwindow;
814f1d2b4d3SLarry Finger 				rtl92c_set_p2p_ctw_period_cmd(hw, ctwindow);
815f1d2b4d3SLarry Finger 			}
816f1d2b4d3SLarry Finger 			/* call refactored routine */
817f1d2b4d3SLarry Finger 			set_noa_data(rtlpriv, p2pinfo, p2p_ps_offload);
818f1d2b4d3SLarry Finger 
819f1d2b4d3SLarry Finger 			if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
820f1d2b4d3SLarry Finger 				/* rst p2p circuit */
821f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST,
822f1d2b4d3SLarry Finger 					       BIT(4));
823f1d2b4d3SLarry Finger 
824f1d2b4d3SLarry Finger 				p2p_ps_offload->offload_en = 1;
825f1d2b4d3SLarry Finger 
826f1d2b4d3SLarry Finger 				if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
827f1d2b4d3SLarry Finger 					p2p_ps_offload->role = 1;
828f1d2b4d3SLarry Finger 					p2p_ps_offload->allstasleep = 0;
829f1d2b4d3SLarry Finger 				} else {
830f1d2b4d3SLarry Finger 					p2p_ps_offload->role = 0;
831f1d2b4d3SLarry Finger 				}
832f1d2b4d3SLarry Finger 
833f1d2b4d3SLarry Finger 				p2p_ps_offload->discovery = 0;
834f1d2b4d3SLarry Finger 			}
835f1d2b4d3SLarry Finger 			break;
836f1d2b4d3SLarry Finger 	case P2P_PS_SCAN:
837f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
838f1d2b4d3SLarry Finger 			p2p_ps_offload->discovery = 1;
839f1d2b4d3SLarry Finger 			break;
840f1d2b4d3SLarry Finger 	case P2P_PS_SCAN_DONE:
841f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
842f1d2b4d3SLarry Finger 				 "P2P_PS_SCAN_DONE\n");
843f1d2b4d3SLarry Finger 			p2p_ps_offload->discovery = 0;
844f1d2b4d3SLarry Finger 			p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
845f1d2b4d3SLarry Finger 			break;
846f1d2b4d3SLarry Finger 	default:
847f1d2b4d3SLarry Finger 			break;
848f1d2b4d3SLarry Finger 	}
849f1d2b4d3SLarry Finger 
850f1d2b4d3SLarry Finger 	rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
851f1d2b4d3SLarry Finger 
852f1d2b4d3SLarry Finger }
853f1d2b4d3SLarry Finger EXPORT_SYMBOL_GPL(rtl92c_set_p2p_ps_offload_cmd);
854