1 /******************************************************************************
3 * Copyright(c) 2009-2014 Realtek Corporation.
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.
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
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
36 static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
38 struct rtl_priv *rtlpriv = rtl_priv(hw);
42 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
44 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
45 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
47 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
48 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
52 static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
53 enum version_8192e version,
56 struct rtl_priv *rtlpriv = rtl_priv(hw);
57 u8 *bufferptr = (u8 *)buffer;
58 u32 pagenums, remainsize;
61 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size);
63 rtl_fill_dummy(bufferptr, &size);
65 pagenums = size / FW_8192C_PAGE_SIZE;
66 remainsize = size % FW_8192C_PAGE_SIZE;
69 pr_err("Page numbers should not greater then 8\n");
71 for (page = 0; page < pagenums; page++) {
72 offset = page * FW_8192C_PAGE_SIZE;
73 rtl_fw_page_write(hw, page, (bufferptr + offset),
79 offset = pagenums * FW_8192C_PAGE_SIZE;
81 rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
85 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
87 struct rtl_priv *rtlpriv = rtl_priv(hw);
93 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
94 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
95 (!(value32 & FWDL_CHKSUM_RPT)));
97 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
98 pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
102 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
103 value32 |= MCUFWDL_RDY;
104 value32 &= ~WINTINI_RDY;
105 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
107 rtl92ee_firmware_selfreset(hw);
111 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
112 if (value32 & WINTINI_RDY)
115 udelay(FW_8192C_POLLING_DELAY*10);
117 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
119 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
126 int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
128 struct rtl_priv *rtlpriv = rtl_priv(hw);
129 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
130 struct rtlwifi_firmware_header *pfwheader;
134 enum version_8192e version = rtlhal->version;
136 if (!rtlhal->pfirmware)
139 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
140 rtlhal->fw_version = le16_to_cpu(pfwheader->version);
141 rtlhal->fw_subversion = pfwheader->subversion;
142 pfwdata = (u8 *)rtlhal->pfirmware;
143 fwsize = rtlhal->fwsize;
144 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
145 "normal Firmware SIZE %d\n" , fwsize);
147 if (IS_FW_HEADER_EXIST(pfwheader)) {
148 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
149 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
150 pfwheader->version, pfwheader->signature,
151 (int)sizeof(struct rtlwifi_firmware_header));
153 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
154 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
156 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
157 "Firmware no Header, Signature(%#x)\n",
158 pfwheader->signature);
161 if (rtlhal->mac_func_enable) {
162 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
163 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
164 rtl92ee_firmware_selfreset(hw);
167 _rtl92ee_enable_fw_download(hw, true);
168 _rtl92ee_write_fw(hw, version, pfwdata, fwsize);
169 _rtl92ee_enable_fw_download(hw, false);
171 err = _rtl92ee_fw_free_to_go(hw);
176 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
178 struct rtl_priv *rtlpriv = rtl_priv(hw);
182 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
183 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
188 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
189 u32 cmd_len, u8 *cmdbuffer)
191 struct rtl_priv *rtlpriv = rtl_priv(hw);
192 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
193 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
195 u16 box_reg = 0, box_extreg = 0;
197 bool isfw_read = false;
199 bool bwrite_sucess = false;
200 u8 wait_h2c_limmit = 100;
201 u8 boxcontent[4], boxextcontent[4];
202 u32 h2c_waitcounter = 0;
206 if (ppsc->dot11_psmode != EACTIVE ||
207 ppsc->inactive_pwrstate == ERFOFF) {
208 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
209 "FillH2CCommand8192E(): Return because RF is off!!!\n");
213 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n");
215 /* 1. Prevent race condition in setting H2C cmd.
216 * (copy from MgntActSet_RF_State().)
219 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
220 if (rtlhal->h2c_setinprogress) {
221 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
222 "H2C set in progress! Wait to set..element_id(%d).\n",
225 while (rtlhal->h2c_setinprogress) {
226 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
229 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
230 "Wait 100 us (%d times)...\n",
234 if (h2c_waitcounter > 1000)
236 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
239 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
241 rtlhal->h2c_setinprogress = true;
242 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
247 while (!bwrite_sucess) {
248 /* 2. Find the last BOX number which has been writen. */
249 boxnum = rtlhal->last_hmeboxnum;
252 box_reg = REG_HMEBOX_0;
253 box_extreg = REG_HMEBOX_EXT_0;
256 box_reg = REG_HMEBOX_1;
257 box_extreg = REG_HMEBOX_EXT_1;
260 box_reg = REG_HMEBOX_2;
261 box_extreg = REG_HMEBOX_EXT_2;
264 box_reg = REG_HMEBOX_3;
265 box_extreg = REG_HMEBOX_EXT_3;
268 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
269 "switch case %#x not processed\n", boxnum);
273 /* 3. Check if the box content is empty. */
275 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
277 if (u1b_tmp != 0xea) {
280 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
281 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
282 rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
286 wait_h2c_limmit = 100;
287 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
290 if (wait_h2c_limmit == 0) {
291 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
292 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
298 _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
299 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
300 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
301 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
306 /* If Fw has not read the last
307 * H2C cmd, break and give up this H2C.
310 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
311 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
315 /* 4. Fill the H2C cmd into box */
316 memset(boxcontent, 0, sizeof(boxcontent));
317 memset(boxextcontent, 0, sizeof(boxextcontent));
318 boxcontent[0] = element_id;
319 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
320 "Write element_id box_reg(%4x) = %2x\n",
321 box_reg, element_id);
327 /*boxcontent[0] &= ~(BIT(7));*/
328 memcpy((u8 *)(boxcontent) + 1,
329 cmdbuffer + buf_index, cmd_len);
331 for (idx = 0; idx < 4; idx++) {
332 rtl_write_byte(rtlpriv, box_reg + idx,
340 /*boxcontent[0] |= (BIT(7));*/
341 memcpy((u8 *)(boxextcontent),
342 cmdbuffer + buf_index+3, cmd_len-3);
343 memcpy((u8 *)(boxcontent) + 1,
344 cmdbuffer + buf_index, 3);
346 for (idx = 0; idx < 4; idx++) {
347 rtl_write_byte(rtlpriv, box_extreg + idx,
351 for (idx = 0; idx < 4; idx++) {
352 rtl_write_byte(rtlpriv, box_reg + idx,
357 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
358 "switch case %#x not processed\n", cmd_len);
362 bwrite_sucess = true;
364 rtlhal->last_hmeboxnum = boxnum + 1;
365 if (rtlhal->last_hmeboxnum == 4)
366 rtlhal->last_hmeboxnum = 0;
368 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
369 "pHalData->last_hmeboxnum = %d\n",
370 rtlhal->last_hmeboxnum);
373 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
374 rtlhal->h2c_setinprogress = false;
375 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
377 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n");
380 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
381 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
383 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
386 if (!rtlhal->fw_ready) {
388 "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
392 memset(tmp_cmdbuf, 0, 8);
393 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
394 _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
397 void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
400 struct rtl_priv *rtlpriv = rtl_priv(hw);
402 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
403 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
405 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
406 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
410 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
411 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
413 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
414 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
416 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD ,
417 " _8051Reset92E(): 8051 reset success .\n");
420 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
422 struct rtl_priv *rtlpriv = rtl_priv(hw);
423 u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
424 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
425 u8 rlbm, power_state = 0, byte5 = 0;
426 u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
427 struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
428 bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
429 btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
430 bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
431 btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
434 mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
436 RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
448 case FW_PS_DTIM_MODE:
450 awake_intvl = ppsc->reg_max_lps_awakeintvl;
451 /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
452 * is only used in swlps.
461 if (rtlpriv->mac80211.p2p) {
466 if (mode == FW_PS_ACTIVE_MODE) {
468 power_state = FW_PWR_STATE_ACTIVE;
471 byte5 = btc_ops->btc_get_lps_val(rtlpriv);
472 power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
474 if ((rlbm == 2) && (byte5 & BIT(4))) {
475 /* Keep awake interval to 1 to prevent from
476 * decreasing coex performance
483 power_state = FW_PWR_STATE_RF_OFF;
487 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
488 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
489 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
491 ((rtlpriv->mac80211.p2p) ?
492 ppsc->smart_ps : 1));
493 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
495 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
496 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
497 SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
499 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
500 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
501 u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
502 if (rtlpriv->cfg->ops->get_btc_status())
503 btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
504 H2C_92E_PWEMODE_LENGTH);
505 rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
509 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
511 u8 parm[3] = { 0 , 0 , 0 };
512 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
513 * bit1=0-->update Media Status to MACID
514 * bit1=1-->update Media Status from MACID to MACID_End
515 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
519 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
520 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
522 rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
525 #define BEACON_PG 0 /* ->1 */
528 #define PROBERSP_PG 4 /* ->5 */
529 #define QOS_NULL_PG 6
530 #define BT_QOS_NULL_PG 7
532 #define TOTAL_RESERVED_PKT_LEN 1024
534 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
536 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
537 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
538 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
541 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
542 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
543 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
544 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
545 0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
549 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
550 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
551 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
554 0x00, 0x50, 0xF2, 0x02, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
573 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
591 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
592 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
593 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607 /* page 4 probe_resp */
608 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
609 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
610 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
611 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
612 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
613 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
614 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
615 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
616 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
617 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
618 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
622 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 /* page 5 probe_resp */
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 /* page 6 qos null data */
640 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
641 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
642 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
652 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 /* page 7 BT-qos null data */
658 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
659 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
660 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
682 struct rtl_priv *rtlpriv = rtl_priv(hw);
683 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
684 struct sk_buff *skb = NULL;
687 u8 u1rsvdpageloc[5] = { 0 };
696 /*---------------------------------------------------------
698 *---------------------------------------------------------
700 beacon = &reserved_page_packet[BEACON_PG * 128];
701 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
702 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
704 /*-------------------------------------------------------
706 *--------------------------------------------------------
708 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
709 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
710 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
711 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
713 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
715 /*--------------------------------------------------------
717 *---------------------------------------------------------
719 nullfunc = &reserved_page_packet[NULL_PG * 128];
720 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
721 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
722 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
724 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
726 /*---------------------------------------------------------
728 *----------------------------------------------------------
730 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
731 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
732 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
733 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
735 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
737 /*---------------------------------------------------------
739 *----------------------------------------------------------
741 qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
742 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
743 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
744 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
746 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
748 /*---------------------------------------------------------
749 * (6) BT QoS null data
750 *----------------------------------------------------------
752 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
753 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
754 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
755 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
757 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
759 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
761 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
762 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
763 &reserved_page_packet[0], totalpacketlen);
764 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
765 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
768 skb = dev_alloc_skb(totalpacketlen);
771 skb_put_data(skb, &reserved_page_packet, totalpacketlen);
773 rtstatus = rtl_cmd_send_packet(hw, skb);
778 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
779 "Set RSVD page location to Fw.\n");
780 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
781 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
782 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
783 sizeof(u1rsvdpageloc), u1rsvdpageloc);
785 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
786 "Set RSVD page location to Fw FAIL!!!!!!.\n");
790 /*Shoud check FW support p2p or not.*/
791 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
793 u8 u1_ctwindow_period[1] = {ctwindow};
795 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
798 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
800 struct rtl_priv *rtlpriv = rtl_priv(hw);
801 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
802 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
803 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
804 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
807 u32 start_time, tsf_low;
809 switch (p2p_ps_state) {
811 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
812 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
815 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
816 /* update CTWindow value. */
817 if (p2pinfo->ctwindow > 0) {
818 p2p_ps_offload->ctwindow_en = 1;
819 ctwindow = p2pinfo->ctwindow;
820 rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
822 /* hw only support 2 set of NoA */
823 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
824 /* To control the register setting for which NOA*/
825 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
827 p2p_ps_offload->noa0_en = 1;
829 p2p_ps_offload->noa1_en = 1;
830 /* config P2P NoA Descriptor Register */
831 rtl_write_dword(rtlpriv, 0x5E0,
832 p2pinfo->noa_duration[i]);
833 rtl_write_dword(rtlpriv, 0x5E4,
834 p2pinfo->noa_interval[i]);
836 /*Get Current TSF value */
837 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
839 start_time = p2pinfo->noa_start_time[i];
840 if (p2pinfo->noa_count_type[i] != 1) {
841 while (start_time <= (tsf_low + (50 * 1024))) {
842 start_time += p2pinfo->noa_interval[i];
843 if (p2pinfo->noa_count_type[i] != 255)
844 p2pinfo->noa_count_type[i]--;
847 rtl_write_dword(rtlpriv, 0x5E8, start_time);
848 rtl_write_dword(rtlpriv, 0x5EC,
849 p2pinfo->noa_count_type[i]);
851 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
852 /* rst p2p circuit */
853 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
854 p2p_ps_offload->offload_en = 1;
856 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
857 p2p_ps_offload->role = 1;
858 p2p_ps_offload->allstasleep = 0;
860 p2p_ps_offload->role = 0;
862 p2p_ps_offload->discovery = 0;
866 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
867 p2p_ps_offload->discovery = 1;
869 case P2P_PS_SCAN_DONE:
870 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
871 p2p_ps_offload->discovery = 0;
872 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
877 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
878 (u8 *)p2p_ps_offload);
881 void rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
882 u8 *cmd_buf, u8 cmd_len)
884 u8 rate = cmd_buf[0] & 0x3F;
885 bool collision_state = cmd_buf[3] & BIT(0);
887 rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);