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