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