1fbb35286SLarry Finger // SPDX-License-Identifier: GPL-2.0
2fbb35286SLarry Finger /* Copyright(c) 2009-2013 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
_rtl88e_enable_fw_download(struct ieee80211_hw * hw,bool enable)13f1d2b4d3SLarry Finger static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable)
14f1d2b4d3SLarry Finger {
15f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
16f1d2b4d3SLarry Finger u8 tmp;
17f1d2b4d3SLarry Finger
18f1d2b4d3SLarry Finger if (enable) {
19f1d2b4d3SLarry Finger tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
20f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
21f1d2b4d3SLarry Finger
22f1d2b4d3SLarry Finger tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
23f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
24f1d2b4d3SLarry Finger
25f1d2b4d3SLarry Finger tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
26f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
27f1d2b4d3SLarry Finger } else {
28f1d2b4d3SLarry Finger tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
29f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
30f1d2b4d3SLarry Finger
31f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
32f1d2b4d3SLarry Finger }
33f1d2b4d3SLarry Finger }
34f1d2b4d3SLarry Finger
_rtl88e_write_fw(struct ieee80211_hw * hw,enum version_8188e version,u8 * buffer,u32 size)35f1d2b4d3SLarry Finger static void _rtl88e_write_fw(struct ieee80211_hw *hw,
36f1d2b4d3SLarry Finger enum version_8188e version, u8 *buffer, u32 size)
37f1d2b4d3SLarry Finger {
38f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
39f1d2b4d3SLarry Finger u8 *bufferptr = (u8 *)buffer;
40f1d2b4d3SLarry Finger u32 pagenums, remainsize;
41f1d2b4d3SLarry Finger u32 page, offset;
42f1d2b4d3SLarry Finger
43*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
44f1d2b4d3SLarry Finger
4589d32c90SLarry Finger rtl_fill_dummy(bufferptr, &size);
46f1d2b4d3SLarry Finger
47f1d2b4d3SLarry Finger pagenums = size / FW_8192C_PAGE_SIZE;
48f1d2b4d3SLarry Finger remainsize = size % FW_8192C_PAGE_SIZE;
49f1d2b4d3SLarry Finger
5002527a73SLarry Finger if (pagenums > 8)
5102527a73SLarry Finger pr_err("Page numbers should not greater then 8\n");
52f1d2b4d3SLarry Finger
53f1d2b4d3SLarry Finger for (page = 0; page < pagenums; page++) {
54f1d2b4d3SLarry Finger offset = page * FW_8192C_PAGE_SIZE;
5589d32c90SLarry Finger rtl_fw_page_write(hw, page, (bufferptr + offset),
56f1d2b4d3SLarry Finger FW_8192C_PAGE_SIZE);
57f1d2b4d3SLarry Finger }
58f1d2b4d3SLarry Finger
59f1d2b4d3SLarry Finger if (remainsize) {
60f1d2b4d3SLarry Finger offset = pagenums * FW_8192C_PAGE_SIZE;
61f1d2b4d3SLarry Finger page = pagenums;
6289d32c90SLarry Finger rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
63f1d2b4d3SLarry Finger }
64f1d2b4d3SLarry Finger }
65f1d2b4d3SLarry Finger
_rtl88e_fw_free_to_go(struct ieee80211_hw * hw)66f1d2b4d3SLarry Finger static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw)
67f1d2b4d3SLarry Finger {
68f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
69f1d2b4d3SLarry Finger int err = -EIO;
70f1d2b4d3SLarry Finger u32 counter = 0;
71f1d2b4d3SLarry Finger u32 value32;
72f1d2b4d3SLarry Finger
73f1d2b4d3SLarry Finger do {
74f1d2b4d3SLarry Finger value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
75f1d2b4d3SLarry Finger } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
76f1d2b4d3SLarry Finger (!(value32 & FWDL_CHKSUM_RPT)));
77f1d2b4d3SLarry Finger
78f1d2b4d3SLarry Finger if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
7902527a73SLarry Finger pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n",
80f1d2b4d3SLarry Finger value32);
81f1d2b4d3SLarry Finger goto exit;
82f1d2b4d3SLarry Finger }
83f1d2b4d3SLarry Finger value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
84f1d2b4d3SLarry Finger value32 |= MCUFWDL_RDY;
85f1d2b4d3SLarry Finger value32 &= ~WINTINI_RDY;
86f1d2b4d3SLarry Finger rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
87f1d2b4d3SLarry Finger
88f1d2b4d3SLarry Finger rtl88e_firmware_selfreset(hw);
89f1d2b4d3SLarry Finger counter = 0;
90f1d2b4d3SLarry Finger
91f1d2b4d3SLarry Finger do {
92f1d2b4d3SLarry Finger value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
9302527a73SLarry Finger if (value32 & WINTINI_RDY)
9402527a73SLarry Finger return 0;
95f1d2b4d3SLarry Finger
96f1d2b4d3SLarry Finger udelay(FW_8192C_POLLING_DELAY);
97f1d2b4d3SLarry Finger
98f1d2b4d3SLarry Finger } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
99f1d2b4d3SLarry Finger
10002527a73SLarry Finger pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n",
10102527a73SLarry Finger value32);
102f1d2b4d3SLarry Finger
103f1d2b4d3SLarry Finger exit:
104f1d2b4d3SLarry Finger return err;
105f1d2b4d3SLarry Finger }
106f1d2b4d3SLarry Finger
rtl88e_download_fw(struct ieee80211_hw * hw,bool buse_wake_on_wlan_fw)107f1d2b4d3SLarry Finger int rtl88e_download_fw(struct ieee80211_hw *hw,
108f1d2b4d3SLarry Finger bool buse_wake_on_wlan_fw)
109f1d2b4d3SLarry Finger {
110f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
111f1d2b4d3SLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
112f1d2b4d3SLarry Finger struct rtlwifi_firmware_header *pfwheader;
113f1d2b4d3SLarry Finger u8 *pfwdata;
114f1d2b4d3SLarry Finger u32 fwsize;
115f1d2b4d3SLarry Finger int err;
116f1d2b4d3SLarry Finger enum version_8188e version = rtlhal->version;
117f1d2b4d3SLarry Finger
118f1d2b4d3SLarry Finger if (!rtlhal->pfirmware)
119f1d2b4d3SLarry Finger return 1;
120f1d2b4d3SLarry Finger
121f1d2b4d3SLarry Finger pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
122874e837dSPing-Ke Shih rtlhal->fw_version = le16_to_cpu(pfwheader->version);
123874e837dSPing-Ke Shih rtlhal->fw_subversion = pfwheader->subversion;
124f1d2b4d3SLarry Finger pfwdata = rtlhal->pfirmware;
125f1d2b4d3SLarry Finger fwsize = rtlhal->fwsize;
126*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
127f1d2b4d3SLarry Finger "normal Firmware SIZE %d\n", fwsize);
128f1d2b4d3SLarry Finger
129f1d2b4d3SLarry Finger if (IS_FW_HEADER_EXIST(pfwheader)) {
130*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
131f1d2b4d3SLarry Finger "Firmware Version(%d), Signature(%#x), Size(%d)\n",
132f1d2b4d3SLarry Finger pfwheader->version, pfwheader->signature,
133f1d2b4d3SLarry Finger (int)sizeof(struct rtlwifi_firmware_header));
134f1d2b4d3SLarry Finger
135f1d2b4d3SLarry Finger pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
136f1d2b4d3SLarry Finger fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
137f1d2b4d3SLarry Finger }
138f1d2b4d3SLarry Finger
139f1d2b4d3SLarry Finger if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
140f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
141f1d2b4d3SLarry Finger rtl88e_firmware_selfreset(hw);
142f1d2b4d3SLarry Finger }
143f1d2b4d3SLarry Finger _rtl88e_enable_fw_download(hw, true);
144f1d2b4d3SLarry Finger _rtl88e_write_fw(hw, version, pfwdata, fwsize);
145f1d2b4d3SLarry Finger _rtl88e_enable_fw_download(hw, false);
146f1d2b4d3SLarry Finger
147f1d2b4d3SLarry Finger err = _rtl88e_fw_free_to_go(hw);
148c93ac39dSLarry Finger if (err)
14902527a73SLarry Finger pr_err("Firmware is not ready to run!\n");
150f1d2b4d3SLarry Finger
151f1d2b4d3SLarry Finger return 0;
152f1d2b4d3SLarry Finger }
153f1d2b4d3SLarry Finger
_rtl88e_check_fw_read_last_h2c(struct ieee80211_hw * hw,u8 boxnum)154f1d2b4d3SLarry Finger static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
155f1d2b4d3SLarry Finger {
156f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
157f1d2b4d3SLarry Finger u8 val_hmetfr;
158f1d2b4d3SLarry Finger
159f1d2b4d3SLarry Finger val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
160f1d2b4d3SLarry Finger if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
161f1d2b4d3SLarry Finger return true;
162f1d2b4d3SLarry Finger return false;
163f1d2b4d3SLarry Finger }
164f1d2b4d3SLarry Finger
_rtl88e_fill_h2c_command(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmd_b)165f1d2b4d3SLarry Finger static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw,
166f1d2b4d3SLarry Finger u8 element_id, u32 cmd_len,
167f1d2b4d3SLarry Finger u8 *cmd_b)
168f1d2b4d3SLarry Finger {
169f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
170f1d2b4d3SLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
171f1d2b4d3SLarry Finger u8 boxnum;
172f1d2b4d3SLarry Finger u16 box_reg = 0, box_extreg = 0;
173f1d2b4d3SLarry Finger u8 u1b_tmp;
174f1d2b4d3SLarry Finger bool isfw_read = false;
175f1d2b4d3SLarry Finger u8 buf_index = 0;
176f1d2b4d3SLarry Finger bool write_sucess = false;
177f1d2b4d3SLarry Finger u8 wait_h2c_limmit = 100;
178f1d2b4d3SLarry Finger u8 wait_writeh2c_limit = 100;
179f1d2b4d3SLarry Finger u8 boxcontent[4], boxextcontent[4];
180f1d2b4d3SLarry Finger u32 h2c_waitcounter = 0;
181f1d2b4d3SLarry Finger unsigned long flag;
182f1d2b4d3SLarry Finger u8 idx;
183f1d2b4d3SLarry Finger
184*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
185f1d2b4d3SLarry Finger
186f1d2b4d3SLarry Finger while (true) {
187f1d2b4d3SLarry Finger spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
188f1d2b4d3SLarry Finger if (rtlhal->h2c_setinprogress) {
189*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
190f1d2b4d3SLarry Finger "H2C set in progress! Wait to set..element_id(%d).\n",
191f1d2b4d3SLarry Finger element_id);
192f1d2b4d3SLarry Finger
193f1d2b4d3SLarry Finger while (rtlhal->h2c_setinprogress) {
194f1d2b4d3SLarry Finger spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
195f1d2b4d3SLarry Finger flag);
196f1d2b4d3SLarry Finger h2c_waitcounter++;
197*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
198f1d2b4d3SLarry Finger "Wait 100 us (%d times)...\n",
199f1d2b4d3SLarry Finger h2c_waitcounter);
200f1d2b4d3SLarry Finger udelay(100);
201f1d2b4d3SLarry Finger
202f1d2b4d3SLarry Finger if (h2c_waitcounter > 1000)
203f1d2b4d3SLarry Finger return;
204f1d2b4d3SLarry Finger spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
205f1d2b4d3SLarry Finger flag);
206f1d2b4d3SLarry Finger }
207f1d2b4d3SLarry Finger spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
208f1d2b4d3SLarry Finger } else {
209f1d2b4d3SLarry Finger rtlhal->h2c_setinprogress = true;
210f1d2b4d3SLarry Finger spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
211f1d2b4d3SLarry Finger break;
212f1d2b4d3SLarry Finger }
213f1d2b4d3SLarry Finger }
214f1d2b4d3SLarry Finger
215f1d2b4d3SLarry Finger while (!write_sucess) {
216f1d2b4d3SLarry Finger wait_writeh2c_limit--;
217f1d2b4d3SLarry Finger if (wait_writeh2c_limit == 0) {
21802527a73SLarry Finger pr_err("Write H2C fail because no trigger for FW INT!\n");
219f1d2b4d3SLarry Finger break;
220f1d2b4d3SLarry Finger }
221f1d2b4d3SLarry Finger
222f1d2b4d3SLarry Finger boxnum = rtlhal->last_hmeboxnum;
223f1d2b4d3SLarry Finger switch (boxnum) {
224f1d2b4d3SLarry Finger case 0:
225f1d2b4d3SLarry Finger box_reg = REG_HMEBOX_0;
226f1d2b4d3SLarry Finger box_extreg = REG_HMEBOX_EXT_0;
227f1d2b4d3SLarry Finger break;
228f1d2b4d3SLarry Finger case 1:
229f1d2b4d3SLarry Finger box_reg = REG_HMEBOX_1;
230f1d2b4d3SLarry Finger box_extreg = REG_HMEBOX_EXT_1;
231f1d2b4d3SLarry Finger break;
232f1d2b4d3SLarry Finger case 2:
233f1d2b4d3SLarry Finger box_reg = REG_HMEBOX_2;
234f1d2b4d3SLarry Finger box_extreg = REG_HMEBOX_EXT_2;
235f1d2b4d3SLarry Finger break;
236f1d2b4d3SLarry Finger case 3:
237f1d2b4d3SLarry Finger box_reg = REG_HMEBOX_3;
238f1d2b4d3SLarry Finger box_extreg = REG_HMEBOX_EXT_3;
239f1d2b4d3SLarry Finger break;
240f1d2b4d3SLarry Finger default:
241*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
242ad574889SJoe Perches "switch case %#x not processed\n", boxnum);
243f1d2b4d3SLarry Finger break;
244f1d2b4d3SLarry Finger }
245f1d2b4d3SLarry Finger isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
246f1d2b4d3SLarry Finger while (!isfw_read) {
247f1d2b4d3SLarry Finger wait_h2c_limmit--;
248f1d2b4d3SLarry Finger if (wait_h2c_limmit == 0) {
249*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
250f1d2b4d3SLarry Finger "Waiting too long for FW read clear HMEBox(%d)!\n",
251f1d2b4d3SLarry Finger boxnum);
252f1d2b4d3SLarry Finger break;
253f1d2b4d3SLarry Finger }
254f1d2b4d3SLarry Finger
255f1d2b4d3SLarry Finger udelay(10);
256f1d2b4d3SLarry Finger
257f1d2b4d3SLarry Finger isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
258f1d2b4d3SLarry Finger u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
259*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
260f1d2b4d3SLarry Finger "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
261f1d2b4d3SLarry Finger boxnum, u1b_tmp);
262f1d2b4d3SLarry Finger }
263f1d2b4d3SLarry Finger
264f1d2b4d3SLarry Finger if (!isfw_read) {
265*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
266f1d2b4d3SLarry Finger "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
267f1d2b4d3SLarry Finger boxnum);
268f1d2b4d3SLarry Finger break;
269f1d2b4d3SLarry Finger }
270f1d2b4d3SLarry Finger
271f1d2b4d3SLarry Finger memset(boxcontent, 0, sizeof(boxcontent));
272f1d2b4d3SLarry Finger memset(boxextcontent, 0, sizeof(boxextcontent));
273f1d2b4d3SLarry Finger boxcontent[0] = element_id;
274*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
275f1d2b4d3SLarry Finger "Write element_id box_reg(%4x) = %2x\n",
276f1d2b4d3SLarry Finger box_reg, element_id);
277f1d2b4d3SLarry Finger
278f1d2b4d3SLarry Finger switch (cmd_len) {
279f1d2b4d3SLarry Finger case 1:
280f1d2b4d3SLarry Finger case 2:
281f1d2b4d3SLarry Finger case 3:
282f1d2b4d3SLarry Finger /*boxcontent[0] &= ~(BIT(7));*/
283f1d2b4d3SLarry Finger memcpy((u8 *)(boxcontent) + 1,
284f1d2b4d3SLarry Finger cmd_b + buf_index, cmd_len);
285f1d2b4d3SLarry Finger
286f1d2b4d3SLarry Finger for (idx = 0; idx < 4; idx++) {
287f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, box_reg + idx,
288f1d2b4d3SLarry Finger boxcontent[idx]);
289f1d2b4d3SLarry Finger }
290f1d2b4d3SLarry Finger break;
291f1d2b4d3SLarry Finger case 4:
292f1d2b4d3SLarry Finger case 5:
293f1d2b4d3SLarry Finger case 6:
294f1d2b4d3SLarry Finger case 7:
295f1d2b4d3SLarry Finger /*boxcontent[0] |= (BIT(7));*/
296f1d2b4d3SLarry Finger memcpy((u8 *)(boxextcontent),
297f1d2b4d3SLarry Finger cmd_b + buf_index+3, cmd_len-3);
298f1d2b4d3SLarry Finger memcpy((u8 *)(boxcontent) + 1,
299f1d2b4d3SLarry Finger cmd_b + buf_index, 3);
300f1d2b4d3SLarry Finger
301f1d2b4d3SLarry Finger for (idx = 0; idx < 2; idx++) {
302f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, box_extreg + idx,
303f1d2b4d3SLarry Finger boxextcontent[idx]);
304f1d2b4d3SLarry Finger }
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 default:
312*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
313ad574889SJoe Perches "switch case %#x not processed\n", cmd_len);
314f1d2b4d3SLarry Finger break;
315f1d2b4d3SLarry Finger }
316f1d2b4d3SLarry Finger
317f1d2b4d3SLarry Finger write_sucess = true;
318f1d2b4d3SLarry Finger
319f1d2b4d3SLarry Finger rtlhal->last_hmeboxnum = boxnum + 1;
320f1d2b4d3SLarry Finger if (rtlhal->last_hmeboxnum == 4)
321f1d2b4d3SLarry Finger rtlhal->last_hmeboxnum = 0;
322f1d2b4d3SLarry Finger
323*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
324f1d2b4d3SLarry Finger "pHalData->last_hmeboxnum = %d\n",
325f1d2b4d3SLarry Finger rtlhal->last_hmeboxnum);
326f1d2b4d3SLarry Finger }
327f1d2b4d3SLarry Finger
328f1d2b4d3SLarry Finger spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
329f1d2b4d3SLarry Finger rtlhal->h2c_setinprogress = false;
330f1d2b4d3SLarry Finger spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
331f1d2b4d3SLarry Finger
332*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
333f1d2b4d3SLarry Finger }
334f1d2b4d3SLarry Finger
rtl88e_fill_h2c_cmd(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)335f1d2b4d3SLarry Finger void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw,
336f1d2b4d3SLarry Finger u8 element_id, u32 cmd_len, u8 *cmdbuffer)
337f1d2b4d3SLarry Finger {
338f1d2b4d3SLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
339f1d2b4d3SLarry Finger u32 tmp_cmdbuf[2];
340f1d2b4d3SLarry Finger
341f1d2b4d3SLarry Finger if (!rtlhal->fw_ready) {
342531940f9SLarry Finger WARN_ONCE(true,
343531940f9SLarry Finger "rtl8188ee: error H2C cmd because of Fw download fail!!!\n");
344f1d2b4d3SLarry Finger return;
345f1d2b4d3SLarry Finger }
346f1d2b4d3SLarry Finger
347f1d2b4d3SLarry Finger memset(tmp_cmdbuf, 0, 8);
348f1d2b4d3SLarry Finger memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
349f1d2b4d3SLarry Finger _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
350f1d2b4d3SLarry Finger
351f1d2b4d3SLarry Finger return;
352f1d2b4d3SLarry Finger }
353f1d2b4d3SLarry Finger
rtl88e_firmware_selfreset(struct ieee80211_hw * hw)354f1d2b4d3SLarry Finger void rtl88e_firmware_selfreset(struct ieee80211_hw *hw)
355f1d2b4d3SLarry Finger {
356f1d2b4d3SLarry Finger u8 u1b_tmp;
357f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
358f1d2b4d3SLarry Finger
359f1d2b4d3SLarry Finger u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
360f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2))));
361f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2)));
362*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
363f1d2b4d3SLarry Finger "8051Reset88E(): 8051 reset success\n");
364f1d2b4d3SLarry Finger
365f1d2b4d3SLarry Finger }
366f1d2b4d3SLarry Finger
rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw * hw,u8 mode)367f1d2b4d3SLarry Finger void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
368f1d2b4d3SLarry Finger {
369f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
370f1d2b4d3SLarry Finger u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 };
371f1d2b4d3SLarry Finger struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
372f1d2b4d3SLarry Finger u8 rlbm, power_state = 0;
373*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
374f1d2b4d3SLarry Finger
3755ea5c93dSLarry Finger set_h2ccmd_pwrmode_parm_mode(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
376f1d2b4d3SLarry Finger rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/
3775ea5c93dSLarry Finger set_h2ccmd_pwrmode_parm_rlbm(u1_h2c_set_pwrmode, rlbm);
3785ea5c93dSLarry Finger set_h2ccmd_pwrmode_parm_smart_ps(u1_h2c_set_pwrmode,
379f1d2b4d3SLarry Finger (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
3805ea5c93dSLarry Finger set_h2ccmd_pwrmode_parm_awake_interval(u1_h2c_set_pwrmode,
381f1d2b4d3SLarry Finger ppsc->reg_max_lps_awakeintvl);
3825ea5c93dSLarry Finger set_h2ccmd_pwrmode_parm_all_queue_uapsd(u1_h2c_set_pwrmode, 0);
383f1d2b4d3SLarry Finger if (mode == FW_PS_ACTIVE_MODE)
384f1d2b4d3SLarry Finger power_state |= FW_PWR_STATE_ACTIVE;
385f1d2b4d3SLarry Finger else
386f1d2b4d3SLarry Finger power_state |= FW_PWR_STATE_RF_OFF;
387f1d2b4d3SLarry Finger
3885ea5c93dSLarry Finger set_h2ccmd_pwrmode_parm_pwr_state(u1_h2c_set_pwrmode, power_state);
389f1d2b4d3SLarry Finger
390f1d2b4d3SLarry Finger RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
391f1d2b4d3SLarry Finger "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
392f1d2b4d3SLarry Finger u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH);
393f1d2b4d3SLarry Finger rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE,
394f1d2b4d3SLarry Finger H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
395f1d2b4d3SLarry Finger }
396f1d2b4d3SLarry Finger
rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw * hw,u8 mstatus)397f1d2b4d3SLarry Finger void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
398f1d2b4d3SLarry Finger {
399f1d2b4d3SLarry Finger u8 u1_joinbssrpt_parm[1] = { 0 };
400f1d2b4d3SLarry Finger
401f1d2b4d3SLarry Finger SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
402f1d2b4d3SLarry Finger
403f1d2b4d3SLarry Finger rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm);
404f1d2b4d3SLarry Finger }
405f1d2b4d3SLarry Finger
rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw * hw,u8 ap_offload_enable)406f1d2b4d3SLarry Finger void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
407f1d2b4d3SLarry Finger u8 ap_offload_enable)
408f1d2b4d3SLarry Finger {
409f1d2b4d3SLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
410f1d2b4d3SLarry Finger u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 };
411f1d2b4d3SLarry Finger
412f1d2b4d3SLarry Finger SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
413f1d2b4d3SLarry Finger SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
414f1d2b4d3SLarry Finger SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
415f1d2b4d3SLarry Finger
416f1d2b4d3SLarry Finger rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD,
417f1d2b4d3SLarry Finger H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm);
418f1d2b4d3SLarry Finger
419f1d2b4d3SLarry Finger }
420f1d2b4d3SLarry Finger
421f1d2b4d3SLarry Finger #define BEACON_PG 0 /* ->1 */
422f1d2b4d3SLarry Finger #define PSPOLL_PG 2
423f1d2b4d3SLarry Finger #define NULL_PG 3
424f1d2b4d3SLarry Finger #define PROBERSP_PG 4 /* ->5 */
425f1d2b4d3SLarry Finger
426f1d2b4d3SLarry Finger #define TOTAL_RESERVED_PKT_LEN 768
427f1d2b4d3SLarry Finger
428f1d2b4d3SLarry Finger static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
429f1d2b4d3SLarry Finger /* page 0 beacon */
430f1d2b4d3SLarry Finger 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
431f1d2b4d3SLarry Finger 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
432f1d2b4d3SLarry Finger 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
433f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434f1d2b4d3SLarry Finger 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
435f1d2b4d3SLarry Finger 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
436f1d2b4d3SLarry Finger 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
437f1d2b4d3SLarry Finger 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
438f1d2b4d3SLarry Finger 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
439f1d2b4d3SLarry Finger 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
440f1d2b4d3SLarry Finger 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443f1d2b4d3SLarry Finger 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
444f1d2b4d3SLarry Finger 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446f1d2b4d3SLarry Finger
447f1d2b4d3SLarry Finger /* page 1 beacon */
448f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460f1d2b4d3SLarry Finger 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
461f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462f1d2b4d3SLarry Finger 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464f1d2b4d3SLarry Finger
465f1d2b4d3SLarry Finger /* page 2 ps-poll */
466f1d2b4d3SLarry Finger 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
467f1d2b4d3SLarry Finger 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
468f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478f1d2b4d3SLarry Finger 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
479f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
480f1d2b4d3SLarry Finger 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482f1d2b4d3SLarry Finger
483f1d2b4d3SLarry Finger /* page 3 null */
484f1d2b4d3SLarry Finger 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
485f1d2b4d3SLarry Finger 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
486f1d2b4d3SLarry Finger 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
487f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496f1d2b4d3SLarry Finger 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
497f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
498f1d2b4d3SLarry Finger 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500f1d2b4d3SLarry Finger
501f1d2b4d3SLarry Finger /* page 4 probe_resp */
502f1d2b4d3SLarry Finger 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
503f1d2b4d3SLarry Finger 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
504f1d2b4d3SLarry Finger 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
505f1d2b4d3SLarry Finger 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
506f1d2b4d3SLarry Finger 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
507f1d2b4d3SLarry Finger 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
508f1d2b4d3SLarry Finger 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
509f1d2b4d3SLarry Finger 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
510f1d2b4d3SLarry Finger 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
511f1d2b4d3SLarry Finger 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
512f1d2b4d3SLarry Finger 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515f1d2b4d3SLarry Finger 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
516f1d2b4d3SLarry Finger 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518f1d2b4d3SLarry Finger
519f1d2b4d3SLarry Finger /* page 5 probe_resp */
520f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529f1d2b4d3SLarry Finger 0x00, 0x00, 0x00, 0x00, 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 };
537f1d2b4d3SLarry Finger
rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw * hw,bool b_dl_finished)538f1d2b4d3SLarry Finger void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
539f1d2b4d3SLarry Finger {
540f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
541f1d2b4d3SLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
542f1d2b4d3SLarry Finger struct sk_buff *skb = NULL;
543f1d2b4d3SLarry Finger u32 totalpacketlen;
544f1d2b4d3SLarry Finger bool rtstatus;
545f1d2b4d3SLarry Finger u8 u1rsvdpageloc[5] = { 0 };
546f1d2b4d3SLarry Finger bool b_dlok = false;
547f1d2b4d3SLarry Finger u8 *beacon;
548f1d2b4d3SLarry Finger u8 *p_pspoll;
549f1d2b4d3SLarry Finger u8 *nullfunc;
550f1d2b4d3SLarry Finger u8 *p_probersp;
551f1d2b4d3SLarry Finger
552f1d2b4d3SLarry Finger /*---------------------------------------------------------
553f1d2b4d3SLarry Finger * (1) beacon
554f1d2b4d3SLarry Finger *---------------------------------------------------------
555f1d2b4d3SLarry Finger */
556f1d2b4d3SLarry Finger beacon = &reserved_page_packet[BEACON_PG * 128];
557f1d2b4d3SLarry Finger SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
558f1d2b4d3SLarry Finger SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
559f1d2b4d3SLarry Finger
560f1d2b4d3SLarry Finger /*-------------------------------------------------------
561f1d2b4d3SLarry Finger * (2) ps-poll
562f1d2b4d3SLarry Finger *--------------------------------------------------------
563f1d2b4d3SLarry Finger */
564f1d2b4d3SLarry Finger p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
565f1d2b4d3SLarry Finger SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
566f1d2b4d3SLarry Finger SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
567f1d2b4d3SLarry Finger SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
568f1d2b4d3SLarry Finger
569f1d2b4d3SLarry Finger SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
570f1d2b4d3SLarry Finger
571f1d2b4d3SLarry Finger /*--------------------------------------------------------
572f1d2b4d3SLarry Finger * (3) null data
573f1d2b4d3SLarry Finger *---------------------------------------------------------
574f1d2b4d3SLarry Finger */
575f1d2b4d3SLarry Finger nullfunc = &reserved_page_packet[NULL_PG * 128];
576f1d2b4d3SLarry Finger SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
577f1d2b4d3SLarry Finger SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
578f1d2b4d3SLarry Finger SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
579f1d2b4d3SLarry Finger
580f1d2b4d3SLarry Finger SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
581f1d2b4d3SLarry Finger
582f1d2b4d3SLarry Finger /*---------------------------------------------------------
583f1d2b4d3SLarry Finger * (4) probe response
584f1d2b4d3SLarry Finger *----------------------------------------------------------
585f1d2b4d3SLarry Finger */
586f1d2b4d3SLarry Finger p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
587f1d2b4d3SLarry Finger SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
588f1d2b4d3SLarry Finger SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
589f1d2b4d3SLarry Finger SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
590f1d2b4d3SLarry Finger
591f1d2b4d3SLarry Finger SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
592f1d2b4d3SLarry Finger
593f1d2b4d3SLarry Finger totalpacketlen = TOTAL_RESERVED_PKT_LEN;
594f1d2b4d3SLarry Finger
595f1d2b4d3SLarry Finger RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
596f1d2b4d3SLarry Finger "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
597f1d2b4d3SLarry Finger &reserved_page_packet[0], totalpacketlen);
598f1d2b4d3SLarry Finger RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
599f1d2b4d3SLarry Finger "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
600f1d2b4d3SLarry Finger u1rsvdpageloc, 3);
601f1d2b4d3SLarry Finger
602f1d2b4d3SLarry Finger skb = dev_alloc_skb(totalpacketlen);
60360209d48SPing-Ke Shih if (!skb)
60460209d48SPing-Ke Shih return;
60559ae1d12SJohannes Berg skb_put_data(skb, &reserved_page_packet, totalpacketlen);
606f1d2b4d3SLarry Finger
607f1d2b4d3SLarry Finger rtstatus = rtl_cmd_send_packet(hw, skb);
608f1d2b4d3SLarry Finger
609f1d2b4d3SLarry Finger if (rtstatus)
610f1d2b4d3SLarry Finger b_dlok = true;
611f1d2b4d3SLarry Finger
612f1d2b4d3SLarry Finger if (b_dlok) {
613*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
614f1d2b4d3SLarry Finger "Set RSVD page location to Fw.\n");
615f1d2b4d3SLarry Finger RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
616f1d2b4d3SLarry Finger "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
617f1d2b4d3SLarry Finger rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE,
618f1d2b4d3SLarry Finger sizeof(u1rsvdpageloc), u1rsvdpageloc);
619f1d2b4d3SLarry Finger } else
620*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
621f1d2b4d3SLarry Finger "Set RSVD page location to Fw FAIL!!!!!!.\n");
622f1d2b4d3SLarry Finger }
623f1d2b4d3SLarry Finger
624f1d2b4d3SLarry Finger /*Should check FW support p2p or not.*/
rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw * hw,u8 ctwindow)625f1d2b4d3SLarry Finger static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
626f1d2b4d3SLarry Finger {
627f1d2b4d3SLarry Finger u8 u1_ctwindow_period[1] = { ctwindow};
628f1d2b4d3SLarry Finger
629f1d2b4d3SLarry Finger rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
630f1d2b4d3SLarry Finger
631f1d2b4d3SLarry Finger }
632f1d2b4d3SLarry Finger
rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw * hw,u8 p2p_ps_state)633f1d2b4d3SLarry Finger void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
634f1d2b4d3SLarry Finger {
635f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
636f1d2b4d3SLarry Finger struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
637f1d2b4d3SLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
638f1d2b4d3SLarry Finger struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
639f1d2b4d3SLarry Finger struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
640f1d2b4d3SLarry Finger u8 i;
641f1d2b4d3SLarry Finger u16 ctwindow;
642f1d2b4d3SLarry Finger u32 start_time, tsf_low;
643f1d2b4d3SLarry Finger
644f1d2b4d3SLarry Finger switch (p2p_ps_state) {
645f1d2b4d3SLarry Finger case P2P_PS_DISABLE:
646*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
647f1d2b4d3SLarry Finger memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
648f1d2b4d3SLarry Finger break;
649f1d2b4d3SLarry Finger case P2P_PS_ENABLE:
650*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
651f1d2b4d3SLarry Finger /* update CTWindow value. */
652f1d2b4d3SLarry Finger if (p2pinfo->ctwindow > 0) {
653f1d2b4d3SLarry Finger p2p_ps_offload->ctwindow_en = 1;
654f1d2b4d3SLarry Finger ctwindow = p2pinfo->ctwindow;
655f1d2b4d3SLarry Finger rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow);
656f1d2b4d3SLarry Finger }
657f1d2b4d3SLarry Finger
658f1d2b4d3SLarry Finger /* hw only support 2 set of NoA */
659f1d2b4d3SLarry Finger for (i = 0 ; i < p2pinfo->noa_num; i++) {
660f1d2b4d3SLarry Finger /* To control the register setting for which NOA*/
661f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
662f1d2b4d3SLarry Finger if (i == 0)
663f1d2b4d3SLarry Finger p2p_ps_offload->noa0_en = 1;
664f1d2b4d3SLarry Finger else
665f1d2b4d3SLarry Finger p2p_ps_offload->noa1_en = 1;
666f1d2b4d3SLarry Finger
667f1d2b4d3SLarry Finger /* config P2P NoA Descriptor Register */
668f1d2b4d3SLarry Finger rtl_write_dword(rtlpriv, 0x5E0,
669f1d2b4d3SLarry Finger p2pinfo->noa_duration[i]);
670f1d2b4d3SLarry Finger rtl_write_dword(rtlpriv, 0x5E4,
671f1d2b4d3SLarry Finger p2pinfo->noa_interval[i]);
672f1d2b4d3SLarry Finger
673f1d2b4d3SLarry Finger /*Get Current TSF value */
674f1d2b4d3SLarry Finger tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
675f1d2b4d3SLarry Finger
676f1d2b4d3SLarry Finger start_time = p2pinfo->noa_start_time[i];
677f1d2b4d3SLarry Finger if (p2pinfo->noa_count_type[i] != 1) {
678f1d2b4d3SLarry Finger while (start_time <= (tsf_low+(50*1024))) {
679f1d2b4d3SLarry Finger start_time += p2pinfo->noa_interval[i];
680f1d2b4d3SLarry Finger if (p2pinfo->noa_count_type[i] != 255)
681f1d2b4d3SLarry Finger p2pinfo->noa_count_type[i]--;
682f1d2b4d3SLarry Finger }
683f1d2b4d3SLarry Finger }
684f1d2b4d3SLarry Finger rtl_write_dword(rtlpriv, 0x5E8, start_time);
685f1d2b4d3SLarry Finger rtl_write_dword(rtlpriv, 0x5EC,
686f1d2b4d3SLarry Finger p2pinfo->noa_count_type[i]);
687f1d2b4d3SLarry Finger }
688f1d2b4d3SLarry Finger
689f1d2b4d3SLarry Finger if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
690f1d2b4d3SLarry Finger /* rst p2p circuit */
691f1d2b4d3SLarry Finger rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
692f1d2b4d3SLarry Finger
693f1d2b4d3SLarry Finger p2p_ps_offload->offload_en = 1;
694f1d2b4d3SLarry Finger
695f1d2b4d3SLarry Finger if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
696f1d2b4d3SLarry Finger p2p_ps_offload->role = 1;
697f1d2b4d3SLarry Finger p2p_ps_offload->allstasleep = -1;
698f1d2b4d3SLarry Finger } else {
699f1d2b4d3SLarry Finger p2p_ps_offload->role = 0;
700f1d2b4d3SLarry Finger }
701f1d2b4d3SLarry Finger
702f1d2b4d3SLarry Finger p2p_ps_offload->discovery = 0;
703f1d2b4d3SLarry Finger }
704f1d2b4d3SLarry Finger break;
705f1d2b4d3SLarry Finger case P2P_PS_SCAN:
706*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
707f1d2b4d3SLarry Finger p2p_ps_offload->discovery = 1;
708f1d2b4d3SLarry Finger break;
709f1d2b4d3SLarry Finger case P2P_PS_SCAN_DONE:
710*57b0b743SLarry Finger rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
711f1d2b4d3SLarry Finger p2p_ps_offload->discovery = 0;
712f1d2b4d3SLarry Finger p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
713f1d2b4d3SLarry Finger break;
714f1d2b4d3SLarry Finger default:
715f1d2b4d3SLarry Finger break;
716f1d2b4d3SLarry Finger }
717f1d2b4d3SLarry Finger
718f1d2b4d3SLarry Finger rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1,
719f1d2b4d3SLarry Finger (u8 *)p2p_ps_offload);
720f1d2b4d3SLarry Finger
721f1d2b4d3SLarry Finger }
722