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