blob: 8d4cf2edeed4815e87de2663d0abdf3eaae1f3df [file] [log] [blame]
Larry Fingerf0eb8562013-03-24 22:06:42 -05001/******************************************************************************
2 *
3 * Copyright(c) 2009-2013 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
Larry Fingerf0eb8562013-03-24 22:06:42 -050014 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
16 *
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
21 *
22 * Larry Finger <Larry.Finger@lwfinger.net>
23 *
24 *****************************************************************************/
25
Chen, Chien-Chia2a2ac752013-04-02 22:01:55 +080026#include "../wifi.h"
27#include "../pci.h"
28#include "../base.h"
Larry Fingerf0eb8562013-03-24 22:06:42 -050029#include "reg.h"
30#include "def.h"
31#include "fw.h"
32
Larry Fingerf0eb8562013-03-24 22:06:42 -050033static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable)
34{
35 struct rtl_priv *rtlpriv = rtl_priv(hw);
36 u8 tmp;
37
38 if (enable) {
39 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
40 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
41
42 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
43 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
44
45 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
46 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
47 } else {
48 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
49 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
50
51 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
52 }
53}
54
55static void _rtl88e_fw_block_write(struct ieee80211_hw *hw,
56 const u8 *buffer, u32 size)
57{
58 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Fingerc151aed2014-09-22 09:39:25 -050059 u32 blocksize = sizeof(u32);
60 u8 *bufferptr = (u8 *)buffer;
Larry Fingerf0eb8562013-03-24 22:06:42 -050061 u32 *pu4BytePtr = (u32 *)buffer;
Larry Fingerc151aed2014-09-22 09:39:25 -050062 u32 i, offset, blockcount, remainsize;
Larry Fingerf0eb8562013-03-24 22:06:42 -050063
Larry Fingerc151aed2014-09-22 09:39:25 -050064 blockcount = size / blocksize;
65 remainsize = size % blocksize;
Larry Fingerf0eb8562013-03-24 22:06:42 -050066
Larry Fingerc151aed2014-09-22 09:39:25 -050067 for (i = 0; i < blockcount; i++) {
68 offset = i * blocksize;
Larry Fingerf0eb8562013-03-24 22:06:42 -050069 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
70 *(pu4BytePtr + i));
71 }
72
Larry Fingerc151aed2014-09-22 09:39:25 -050073 if (remainsize) {
74 offset = blockcount * blocksize;
75 bufferptr += offset;
76 for (i = 0; i < remainsize; i++) {
Larry Fingerf0eb8562013-03-24 22:06:42 -050077 rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
Larry Fingerc151aed2014-09-22 09:39:25 -050078 offset + i), *(bufferptr + i));
Larry Fingerf0eb8562013-03-24 22:06:42 -050079 }
80 }
81}
82
83static void _rtl88e_fw_page_write(struct ieee80211_hw *hw,
84 u32 page, const u8 *buffer, u32 size)
85{
86 struct rtl_priv *rtlpriv = rtl_priv(hw);
87 u8 value8;
88 u8 u8page = (u8) (page & 0x07);
89
90 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
91
92 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
93 _rtl88e_fw_block_write(hw, buffer, size);
94}
95
96static void _rtl88e_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
97{
98 u32 fwlen = *pfwlen;
99 u8 remain = (u8) (fwlen % 4);
100
101 remain = (remain == 0) ? 0 : (4 - remain);
102
103 while (remain > 0) {
104 pfwbuf[fwlen] = 0;
105 fwlen++;
106 remain--;
107 }
108
109 *pfwlen = fwlen;
110}
111
112static void _rtl88e_write_fw(struct ieee80211_hw *hw,
113 enum version_8188e version, u8 *buffer, u32 size)
114{
115 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Fingerc151aed2014-09-22 09:39:25 -0500116 u8 *bufferptr = (u8 *)buffer;
117 u32 pagenums, remainsize;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500118 u32 page, offset;
119
120 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
121
Larry Fingerc151aed2014-09-22 09:39:25 -0500122 _rtl88e_fill_dummy(bufferptr, &size);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500123
Larry Fingerc151aed2014-09-22 09:39:25 -0500124 pagenums = size / FW_8192C_PAGE_SIZE;
125 remainsize = size % FW_8192C_PAGE_SIZE;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500126
Larry Fingerc151aed2014-09-22 09:39:25 -0500127 if (pagenums > 8) {
Larry Fingerf0eb8562013-03-24 22:06:42 -0500128 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
129 "Page numbers should not greater then 8\n");
130 }
131
Larry Fingerc151aed2014-09-22 09:39:25 -0500132 for (page = 0; page < pagenums; page++) {
Larry Fingerf0eb8562013-03-24 22:06:42 -0500133 offset = page * FW_8192C_PAGE_SIZE;
Larry Fingerc151aed2014-09-22 09:39:25 -0500134 _rtl88e_fw_page_write(hw, page, (bufferptr + offset),
Larry Fingerf0eb8562013-03-24 22:06:42 -0500135 FW_8192C_PAGE_SIZE);
136 }
137
Larry Fingerc151aed2014-09-22 09:39:25 -0500138 if (remainsize) {
139 offset = pagenums * FW_8192C_PAGE_SIZE;
140 page = pagenums;
141 _rtl88e_fw_page_write(hw, page, (bufferptr + offset),
142 remainsize);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500143 }
144}
145
146static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw)
147{
148 struct rtl_priv *rtlpriv = rtl_priv(hw);
149 int err = -EIO;
150 u32 counter = 0;
151 u32 value32;
152
153 do {
154 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
155 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
156 (!(value32 & FWDL_CHKSUM_RPT)));
157
158 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
159 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
160 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
161 value32);
162 goto exit;
163 }
164
165 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
166 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
167
168 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
169 value32 |= MCUFWDL_RDY;
170 value32 &= ~WINTINI_RDY;
171 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
172
173 rtl88e_firmware_selfreset(hw);
174 counter = 0;
175
176 do {
177 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
178 if (value32 & WINTINI_RDY) {
179 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
180 "Polling FW ready success!! REG_MCUFWDL:0x%08x.\n",
181 value32);
182 err = 0;
183 goto exit;
184 }
185
186 udelay(FW_8192C_POLLING_DELAY);
187
188 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
189
190 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
191 "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
192
193exit:
194 return err;
195}
196
Larry Fingerc151aed2014-09-22 09:39:25 -0500197int rtl88e_download_fw(struct ieee80211_hw *hw,
198 bool buse_wake_on_wlan_fw)
Larry Fingerf0eb8562013-03-24 22:06:42 -0500199{
200 struct rtl_priv *rtlpriv = rtl_priv(hw);
201 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
202 struct rtl92c_firmware_header *pfwheader;
203 u8 *pfwdata;
204 u32 fwsize;
205 int err;
206 enum version_8188e version = rtlhal->version;
207
208 if (!rtlhal->pfirmware)
209 return 1;
210
211 pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
Joe Perches1851cb42014-03-24 13:15:40 -0700212 pfwdata = rtlhal->pfirmware;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500213 fwsize = rtlhal->fwsize;
214 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
215 "normal Firmware SIZE %d\n", fwsize);
216
217 if (IS_FW_HEADER_EXIST(pfwheader)) {
218 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
219 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
Larry Fingerc151aed2014-09-22 09:39:25 -0500220 pfwheader->version, pfwheader->signature,
221 (int)sizeof(struct rtl92c_firmware_header));
Larry Fingerf0eb8562013-03-24 22:06:42 -0500222
223 pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
224 fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
225 }
226
227 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
228 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
229 rtl88e_firmware_selfreset(hw);
230 }
231 _rtl88e_enable_fw_download(hw, true);
232 _rtl88e_write_fw(hw, version, pfwdata, fwsize);
233 _rtl88e_enable_fw_download(hw, false);
234
235 err = _rtl88e_fw_free_to_go(hw);
Larry Fingerc151aed2014-09-22 09:39:25 -0500236 if (err) {
237 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
238 "Firmware is not ready to run!\n");
239 } else {
240 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
241 "Firmware is ready to run!\n");
242 }
Larry Fingerf0eb8562013-03-24 22:06:42 -0500243
Larry Fingerf0eb8562013-03-24 22:06:42 -0500244 return 0;
245}
246
247static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
248{
249 struct rtl_priv *rtlpriv = rtl_priv(hw);
250 u8 val_hmetfr;
251
252 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
253 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
254 return true;
255 return false;
256}
257
258static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw,
259 u8 element_id, u32 cmd_len,
260 u8 *cmd_b)
261{
262 struct rtl_priv *rtlpriv = rtl_priv(hw);
263 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
264 u8 boxnum;
265 u16 box_reg = 0, box_extreg = 0;
266 u8 u1b_tmp;
267 bool isfw_read = false;
268 u8 buf_index = 0;
269 bool write_sucess = false;
Larry Fingerc151aed2014-09-22 09:39:25 -0500270 u8 wait_h2c_limmit = 100;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500271 u8 wait_writeh2c_limit = 100;
Larry Fingerc151aed2014-09-22 09:39:25 -0500272 u8 boxcontent[4], boxextcontent[4];
Larry Fingerf0eb8562013-03-24 22:06:42 -0500273 u32 h2c_waitcounter = 0;
274 unsigned long flag;
275 u8 idx;
276
277 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
278
279 while (true) {
280 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
281 if (rtlhal->h2c_setinprogress) {
282 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
283 "H2C set in progress! Wait to set..element_id(%d).\n",
284 element_id);
285
286 while (rtlhal->h2c_setinprogress) {
287 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
288 flag);
289 h2c_waitcounter++;
290 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
291 "Wait 100 us (%d times)...\n",
292 h2c_waitcounter);
293 udelay(100);
294
295 if (h2c_waitcounter > 1000)
296 return;
297 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
298 flag);
299 }
300 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
301 } else {
302 rtlhal->h2c_setinprogress = true;
303 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
304 break;
305 }
306 }
307
308 while (!write_sucess) {
309 wait_writeh2c_limit--;
310 if (wait_writeh2c_limit == 0) {
311 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
312 "Write H2C fail because no trigger for FW INT!\n");
313 break;
314 }
315
316 boxnum = rtlhal->last_hmeboxnum;
317 switch (boxnum) {
318 case 0:
319 box_reg = REG_HMEBOX_0;
320 box_extreg = REG_HMEBOX_EXT_0;
321 break;
322 case 1:
323 box_reg = REG_HMEBOX_1;
324 box_extreg = REG_HMEBOX_EXT_1;
325 break;
326 case 2:
327 box_reg = REG_HMEBOX_2;
328 box_extreg = REG_HMEBOX_EXT_2;
329 break;
330 case 3:
331 box_reg = REG_HMEBOX_3;
332 box_extreg = REG_HMEBOX_EXT_3;
333 break;
334 default:
Larry Fingerc151aed2014-09-22 09:39:25 -0500335 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
336 "switch case not process\n");
Larry Fingerf0eb8562013-03-24 22:06:42 -0500337 break;
338 }
Larry Fingerf0eb8562013-03-24 22:06:42 -0500339 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
340 while (!isfw_read) {
Larry Fingerc151aed2014-09-22 09:39:25 -0500341 wait_h2c_limmit--;
342 if (wait_h2c_limmit == 0) {
Larry Fingerf0eb8562013-03-24 22:06:42 -0500343 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Fingerc151aed2014-09-22 09:39:25 -0500344 "Waiting too long for FW read clear HMEBox(%d)!\n",
345 boxnum);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500346 break;
347 }
348
349 udelay(10);
350
351 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
352 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
353 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Fingerc151aed2014-09-22 09:39:25 -0500354 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
355 boxnum, u1b_tmp);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500356 }
357
358 if (!isfw_read) {
359 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Fingerc151aed2014-09-22 09:39:25 -0500360 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
361 boxnum);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500362 break;
363 }
364
Larry Fingerc151aed2014-09-22 09:39:25 -0500365 memset(boxcontent, 0, sizeof(boxcontent));
366 memset(boxextcontent, 0, sizeof(boxextcontent));
367 boxcontent[0] = element_id;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500368 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
369 "Write element_id box_reg(%4x) = %2x\n",
370 box_reg, element_id);
371
372 switch (cmd_len) {
373 case 1:
374 case 2:
375 case 3:
Larry Fingerc151aed2014-09-22 09:39:25 -0500376 /*boxcontent[0] &= ~(BIT(7));*/
377 memcpy((u8 *)(boxcontent) + 1,
378 cmd_b + buf_index, cmd_len);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500379
Larry Fingerc151aed2014-09-22 09:39:25 -0500380 for (idx = 0; idx < 4; idx++) {
381 rtl_write_byte(rtlpriv, box_reg + idx,
382 boxcontent[idx]);
383 }
Larry Fingerf0eb8562013-03-24 22:06:42 -0500384 break;
385 case 4:
386 case 5:
387 case 6:
388 case 7:
Larry Fingerc151aed2014-09-22 09:39:25 -0500389 /*boxcontent[0] |= (BIT(7));*/
390 memcpy((u8 *)(boxextcontent),
391 cmd_b + buf_index+3, cmd_len-3);
392 memcpy((u8 *)(boxcontent) + 1,
393 cmd_b + buf_index, 3);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500394
395 for (idx = 0; idx < 2; idx++) {
396 rtl_write_byte(rtlpriv, box_extreg + idx,
Larry Fingerc151aed2014-09-22 09:39:25 -0500397 boxextcontent[idx]);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500398 }
399
400 for (idx = 0; idx < 4; idx++) {
401 rtl_write_byte(rtlpriv, box_reg + idx,
Larry Fingerc151aed2014-09-22 09:39:25 -0500402 boxcontent[idx]);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500403 }
404 break;
405 default:
Larry Fingerc151aed2014-09-22 09:39:25 -0500406 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
407 "switch case not process\n");
Larry Fingerf0eb8562013-03-24 22:06:42 -0500408 break;
409 }
410
411 write_sucess = true;
412
413 rtlhal->last_hmeboxnum = boxnum + 1;
414 if (rtlhal->last_hmeboxnum == 4)
415 rtlhal->last_hmeboxnum = 0;
416
417 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
418 "pHalData->last_hmeboxnum = %d\n",
Larry Fingerc151aed2014-09-22 09:39:25 -0500419 rtlhal->last_hmeboxnum);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500420 }
421
422 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
423 rtlhal->h2c_setinprogress = false;
424 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
425
426 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
427}
428
429void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw,
Larry Fingerc151aed2014-09-22 09:39:25 -0500430 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
Larry Fingerf0eb8562013-03-24 22:06:42 -0500431{
432 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
433 u32 tmp_cmdbuf[2];
434
Larry Fingerc151aed2014-09-22 09:39:25 -0500435 if (!rtlhal->fw_ready) {
436 RT_ASSERT(false,
437 "return H2C cmd because of Fw download fail!!!\n");
Larry Fingerf0eb8562013-03-24 22:06:42 -0500438 return;
439 }
440
441 memset(tmp_cmdbuf, 0, 8);
Larry Fingerc151aed2014-09-22 09:39:25 -0500442 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500443 _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
444
445 return;
446}
447
448void rtl88e_firmware_selfreset(struct ieee80211_hw *hw)
449{
450 u8 u1b_tmp;
451 struct rtl_priv *rtlpriv = rtl_priv(hw);
452
453 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
454 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2))));
455 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2)));
456 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
Larry Fingerc151aed2014-09-22 09:39:25 -0500457 "8051Reset88E(): 8051 reset success\n");
458
Larry Fingerf0eb8562013-03-24 22:06:42 -0500459}
460
461void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
462{
463 struct rtl_priv *rtlpriv = rtl_priv(hw);
464 u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 };
465 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
Larry Fingerc151aed2014-09-22 09:39:25 -0500466 u8 rlbm, power_state = 0;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500467 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
Larry Fingerc151aed2014-09-22 09:39:25 -0500468
Larry Fingerf0eb8562013-03-24 22:06:42 -0500469 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
Larry Fingerc151aed2014-09-22 09:39:25 -0500470 rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/
471 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500472 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
Larry Fingerc151aed2014-09-22 09:39:25 -0500473 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500474 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
Larry Fingerc151aed2014-09-22 09:39:25 -0500475 ppsc->reg_max_lps_awakeintvl);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500476 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
477 if (mode == FW_PS_ACTIVE_MODE)
478 power_state |= FW_PWR_STATE_ACTIVE;
479 else
480 power_state |= FW_PWR_STATE_RF_OFF;
Larry Fingerc151aed2014-09-22 09:39:25 -0500481
Larry Fingerf0eb8562013-03-24 22:06:42 -0500482 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
483
484 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
485 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
486 u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH);
Larry Fingerc151aed2014-09-22 09:39:25 -0500487 rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE,
488 H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500489}
490
491void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
492{
493 u8 u1_joinbssrpt_parm[1] = { 0 };
494
495 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
496
497 rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm);
498}
499
500void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
501 u8 ap_offload_enable)
502{
503 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
504 u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 };
505
506 SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
507 SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
508 SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
509
Larry Fingerc151aed2014-09-22 09:39:25 -0500510 rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD,
511 H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm);
512
Larry Fingerf0eb8562013-03-24 22:06:42 -0500513}
514
515static bool _rtl88e_cmd_send_packet(struct ieee80211_hw *hw,
516 struct sk_buff *skb)
517{
518 struct rtl_priv *rtlpriv = rtl_priv(hw);
519 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
520 struct rtl8192_tx_ring *ring;
521 struct rtl_tx_desc *pdesc;
522 struct sk_buff *pskb = NULL;
Larry Fingerc151aed2014-09-22 09:39:25 -0500523 u8 own;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500524 unsigned long flags;
525
526 ring = &rtlpci->tx_ring[BEACON_QUEUE];
527
528 pskb = __skb_dequeue(&ring->queue);
529 if (pskb)
530 kfree_skb(pskb);
531
532 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
533
534 pdesc = &ring->desc[0];
Larry Fingerc151aed2014-09-22 09:39:25 -0500535 own = (u8)rtlpriv->cfg->ops->get_desc((u8 *)pdesc, true, HW_DESC_OWN);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500536
537 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb);
538
539 __skb_queue_tail(&ring->queue, skb);
540
541 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
542
543 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
544
545 return true;
546}
547
548#define BEACON_PG 0 /* ->1 */
549#define PSPOLL_PG 2
550#define NULL_PG 3
551#define PROBERSP_PG 4 /* ->5 */
552
553#define TOTAL_RESERVED_PKT_LEN 768
554
555static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
556 /* page 0 beacon */
557 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
558 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
559 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
562 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
563 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
564 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
565 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
566 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
567 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
571 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573
574 /* page 1 beacon */
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591
592 /* page 2 ps-poll */
593 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
594 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
607 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609
610 /* page 3 null */
611 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
612 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
613 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
625 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627
628 /* page 4 probe_resp */
629 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
630 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
631 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
632 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
633 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
634 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
635 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
636 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
637 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
638 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
639 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
643 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645
646 /* page 5 probe_resp */
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663};
664
665void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
666{
667 struct rtl_priv *rtlpriv = rtl_priv(hw);
668 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
669 struct sk_buff *skb = NULL;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500670 u32 totalpacketlen;
Larry Fingerc151aed2014-09-22 09:39:25 -0500671 bool rtstatus;
672 u8 u1rsvdpageloc[5] = { 0 };
673 bool b_dlok = false;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500674 u8 *beacon;
Larry Fingerc151aed2014-09-22 09:39:25 -0500675 u8 *p_pspoll;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500676 u8 *nullfunc;
Larry Fingerc151aed2014-09-22 09:39:25 -0500677 u8 *p_probersp;
678
Larry Fingerf0eb8562013-03-24 22:06:42 -0500679 /*---------------------------------------------------------
680 * (1) beacon
681 *---------------------------------------------------------
682 */
683 beacon = &reserved_page_packet[BEACON_PG * 128];
684 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
685 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
686
687 /*-------------------------------------------------------
688 * (2) ps-poll
689 *--------------------------------------------------------
690 */
Larry Fingerc151aed2014-09-22 09:39:25 -0500691 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
692 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
693 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
694 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500695
Larry Fingerc151aed2014-09-22 09:39:25 -0500696 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500697
698 /*--------------------------------------------------------
699 * (3) null data
700 *---------------------------------------------------------
701 */
702 nullfunc = &reserved_page_packet[NULL_PG * 128];
703 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
704 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
705 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
706
Larry Fingerc151aed2014-09-22 09:39:25 -0500707 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500708
709 /*---------------------------------------------------------
710 * (4) probe response
711 *----------------------------------------------------------
712 */
Larry Fingerc151aed2014-09-22 09:39:25 -0500713 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
714 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
715 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
716 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500717
Larry Fingerc151aed2014-09-22 09:39:25 -0500718 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500719
720 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
721
722 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
723 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
724 &reserved_page_packet[0], totalpacketlen);
725 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
726 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
Larry Fingerc151aed2014-09-22 09:39:25 -0500727 u1rsvdpageloc, 3);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500728
729 skb = dev_alloc_skb(totalpacketlen);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500730 memcpy(skb_put(skb, totalpacketlen),
731 &reserved_page_packet, totalpacketlen);
732
Larry Fingerc151aed2014-09-22 09:39:25 -0500733 rtstatus = _rtl88e_cmd_send_packet(hw, skb);
734
735 if (rtstatus)
736 b_dlok = true;
737
738 if (b_dlok) {
Larry Fingerf0eb8562013-03-24 22:06:42 -0500739 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
740 "Set RSVD page location to Fw.\n");
741 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
Larry Fingerc151aed2014-09-22 09:39:25 -0500742 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500743 rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE,
Larry Fingerc151aed2014-09-22 09:39:25 -0500744 sizeof(u1rsvdpageloc), u1rsvdpageloc);
Larry Fingerf0eb8562013-03-24 22:06:42 -0500745 } else
746 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
747 "Set RSVD page location to Fw FAIL!!!!!!.\n");
748}
749
Larry Fingerc151aed2014-09-22 09:39:25 -0500750/*Should check FW support p2p or not.*/
Larry Fingerf0eb8562013-03-24 22:06:42 -0500751static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
752{
Larry Fingerc151aed2014-09-22 09:39:25 -0500753 u8 u1_ctwindow_period[1] = { ctwindow};
Larry Fingerf0eb8562013-03-24 22:06:42 -0500754
755 rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
Larry Fingerc151aed2014-09-22 09:39:25 -0500756
Larry Fingerf0eb8562013-03-24 22:06:42 -0500757}
758
759void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
760{
761 struct rtl_priv *rtlpriv = rtl_priv(hw);
762 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
763 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
764 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
765 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
766 u8 i;
767 u16 ctwindow;
768 u32 start_time, tsf_low;
769
770 switch (p2p_ps_state) {
771 case P2P_PS_DISABLE:
772 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
Larry Finger7fe3b3a2014-09-26 16:40:22 -0500773 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
Larry Fingerf0eb8562013-03-24 22:06:42 -0500774 break;
775 case P2P_PS_ENABLE:
776 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
777 /* update CTWindow value. */
778 if (p2pinfo->ctwindow > 0) {
779 p2p_ps_offload->ctwindow_en = 1;
780 ctwindow = p2pinfo->ctwindow;
781 rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow);
782 }
Larry Fingerc151aed2014-09-22 09:39:25 -0500783
Larry Fingerf0eb8562013-03-24 22:06:42 -0500784 /* hw only support 2 set of NoA */
Larry Fingerc151aed2014-09-22 09:39:25 -0500785 for (i = 0 ; i < p2pinfo->noa_num; i++) {
Larry Fingerf0eb8562013-03-24 22:06:42 -0500786 /* To control the register setting for which NOA*/
787 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
788 if (i == 0)
789 p2p_ps_offload->noa0_en = 1;
790 else
791 p2p_ps_offload->noa1_en = 1;
792
793 /* config P2P NoA Descriptor Register */
794 rtl_write_dword(rtlpriv, 0x5E0,
795 p2pinfo->noa_duration[i]);
796 rtl_write_dword(rtlpriv, 0x5E4,
797 p2pinfo->noa_interval[i]);
798
799 /*Get Current TSF value */
800 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
801
802 start_time = p2pinfo->noa_start_time[i];
803 if (p2pinfo->noa_count_type[i] != 1) {
Larry Fingerc151aed2014-09-22 09:39:25 -0500804 while (start_time <= (tsf_low+(50*1024))) {
Larry Fingerf0eb8562013-03-24 22:06:42 -0500805 start_time += p2pinfo->noa_interval[i];
806 if (p2pinfo->noa_count_type[i] != 255)
807 p2pinfo->noa_count_type[i]--;
808 }
809 }
810 rtl_write_dword(rtlpriv, 0x5E8, start_time);
811 rtl_write_dword(rtlpriv, 0x5EC,
812 p2pinfo->noa_count_type[i]);
813 }
814
815 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
816 /* rst p2p circuit */
817 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
818
819 p2p_ps_offload->offload_en = 1;
820
821 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
822 p2p_ps_offload->role = 1;
Larry Fingerc151aed2014-09-22 09:39:25 -0500823 p2p_ps_offload->allstasleep = -1;
Larry Fingerf0eb8562013-03-24 22:06:42 -0500824 } else {
825 p2p_ps_offload->role = 0;
826 }
827
828 p2p_ps_offload->discovery = 0;
829 }
830 break;
831 case P2P_PS_SCAN:
832 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
833 p2p_ps_offload->discovery = 1;
834 break;
835 case P2P_PS_SCAN_DONE:
836 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
837 p2p_ps_offload->discovery = 0;
838 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
839 break;
840 default:
841 break;
842 }
843
844 rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1,
845 (u8 *)p2p_ps_offload);
Larry Fingerc151aed2014-09-22 09:39:25 -0500846
Larry Fingerf0eb8562013-03-24 22:06:42 -0500847}