Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2014  Realtek Corporation.*/
0003 
0004 #include "../wifi.h"
0005 #include "../pci.h"
0006 #include "../base.h"
0007 #include "../core.h"
0008 #include "../efuse.h"
0009 #include "reg.h"
0010 #include "def.h"
0011 #include "fw.h"
0012 #include "dm.h"
0013 
0014 static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
0015 {
0016     struct rtl_priv *rtlpriv = rtl_priv(hw);
0017     u8 tmp;
0018 
0019     if (enable) {
0020         rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
0021 
0022         tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
0023         rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
0024     } else {
0025         tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
0026         rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
0027     }
0028 }
0029 
0030 static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
0031                   enum version_8192e version,
0032                   u8 *buffer, u32 size)
0033 {
0034     struct rtl_priv *rtlpriv = rtl_priv(hw);
0035     u8 *bufferptr = (u8 *)buffer;
0036     u32 pagenums, remainsize;
0037     u32 page, offset;
0038 
0039     rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
0040 
0041     rtl_fill_dummy(bufferptr, &size);
0042 
0043     pagenums = size / FW_8192C_PAGE_SIZE;
0044     remainsize = size % FW_8192C_PAGE_SIZE;
0045 
0046     if (pagenums > 8)
0047         pr_err("Page numbers should not greater then 8\n");
0048 
0049     for (page = 0; page < pagenums; page++) {
0050         offset = page * FW_8192C_PAGE_SIZE;
0051         rtl_fw_page_write(hw, page, (bufferptr + offset),
0052                   FW_8192C_PAGE_SIZE);
0053         udelay(2);
0054     }
0055 
0056     if (remainsize) {
0057         offset = pagenums * FW_8192C_PAGE_SIZE;
0058         page = pagenums;
0059         rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
0060     }
0061 }
0062 
0063 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
0064 {
0065     struct rtl_priv *rtlpriv = rtl_priv(hw);
0066     int err = -EIO;
0067     u32 counter = 0;
0068     u32 value32;
0069 
0070     do {
0071         value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
0072     } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
0073          (!(value32 & FWDL_CHKSUM_RPT)));
0074 
0075     if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
0076         pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
0077                value32);
0078         goto exit;
0079     }
0080     value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
0081     value32 |= MCUFWDL_RDY;
0082     value32 &= ~WINTINI_RDY;
0083     rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
0084 
0085     rtl92ee_firmware_selfreset(hw);
0086     counter = 0;
0087 
0088     do {
0089         value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
0090         if (value32 & WINTINI_RDY)
0091             return 0;
0092 
0093         udelay(FW_8192C_POLLING_DELAY*10);
0094 
0095     } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
0096 
0097     pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
0098            value32, counter);
0099 
0100 exit:
0101     return err;
0102 }
0103 
0104 int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
0105 {
0106     struct rtl_priv *rtlpriv = rtl_priv(hw);
0107     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0108     struct rtlwifi_firmware_header *pfwheader;
0109     u8 *pfwdata;
0110     u32 fwsize;
0111     enum version_8192e version = rtlhal->version;
0112 
0113     if (!rtlhal->pfirmware)
0114         return 1;
0115 
0116     pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
0117     rtlhal->fw_version = le16_to_cpu(pfwheader->version);
0118     rtlhal->fw_subversion = pfwheader->subversion;
0119     pfwdata = (u8 *)rtlhal->pfirmware;
0120     fwsize = rtlhal->fwsize;
0121     rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
0122         "normal Firmware SIZE %d\n", fwsize);
0123 
0124     if (IS_FW_HEADER_EXIST(pfwheader)) {
0125         rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
0126             "Firmware Version(%d), Signature(%#x),Size(%d)\n",
0127             pfwheader->version, pfwheader->signature,
0128             (int)sizeof(struct rtlwifi_firmware_header));
0129 
0130         pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
0131         fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
0132     } else {
0133         rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
0134             "Firmware no Header, Signature(%#x)\n",
0135             pfwheader->signature);
0136     }
0137 
0138     if (rtlhal->mac_func_enable) {
0139         if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
0140             rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
0141             rtl92ee_firmware_selfreset(hw);
0142         }
0143     }
0144     _rtl92ee_enable_fw_download(hw, true);
0145     _rtl92ee_write_fw(hw, version, pfwdata, fwsize);
0146     _rtl92ee_enable_fw_download(hw, false);
0147 
0148     return _rtl92ee_fw_free_to_go(hw);
0149 }
0150 
0151 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
0152 {
0153     struct rtl_priv *rtlpriv = rtl_priv(hw);
0154     u8 val_hmetfr;
0155     bool result = false;
0156 
0157     val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
0158     if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
0159         result = true;
0160     return result;
0161 }
0162 
0163 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
0164                       u32 cmd_len, u8 *cmdbuffer)
0165 {
0166     struct rtl_priv *rtlpriv = rtl_priv(hw);
0167     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0168     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0169     u8 boxnum;
0170     u16 box_reg = 0, box_extreg = 0;
0171     u8 u1b_tmp;
0172     bool isfw_read = false;
0173     u8 buf_index = 0;
0174     bool bwrite_sucess = false;
0175     u8 wait_h2c_limmit = 100;
0176     u8 boxcontent[4], boxextcontent[4];
0177     u32 h2c_waitcounter = 0;
0178     unsigned long flag;
0179     u8 idx;
0180 
0181     if (ppsc->dot11_psmode != EACTIVE ||
0182         ppsc->inactive_pwrstate == ERFOFF) {
0183         rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0184             "FillH2CCommand8192E(): Return because RF is off!!!\n");
0185         return;
0186     }
0187 
0188     rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
0189 
0190     /* 1. Prevent race condition in setting H2C cmd.
0191      * (copy from MgntActSet_RF_State().)
0192      */
0193     while (true) {
0194         spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
0195         if (rtlhal->h2c_setinprogress) {
0196             rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0197                 "H2C set in progress! Wait to set..element_id(%d).\n",
0198                 element_id);
0199 
0200             while (rtlhal->h2c_setinprogress) {
0201                 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
0202                                flag);
0203                 h2c_waitcounter++;
0204                 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0205                     "Wait 100 us (%d times)...\n",
0206                     h2c_waitcounter);
0207                 udelay(100);
0208 
0209                 if (h2c_waitcounter > 1000)
0210                     return;
0211                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
0212                           flag);
0213             }
0214             spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0215         } else {
0216             rtlhal->h2c_setinprogress = true;
0217             spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0218             break;
0219         }
0220     }
0221 
0222     while (!bwrite_sucess) {
0223         /* 2. Find the last BOX number which has been writen. */
0224         boxnum = rtlhal->last_hmeboxnum;
0225         switch (boxnum) {
0226         case 0:
0227             box_reg = REG_HMEBOX_0;
0228             box_extreg = REG_HMEBOX_EXT_0;
0229             break;
0230         case 1:
0231             box_reg = REG_HMEBOX_1;
0232             box_extreg = REG_HMEBOX_EXT_1;
0233             break;
0234         case 2:
0235             box_reg = REG_HMEBOX_2;
0236             box_extreg = REG_HMEBOX_EXT_2;
0237             break;
0238         case 3:
0239             box_reg = REG_HMEBOX_3;
0240             box_extreg = REG_HMEBOX_EXT_3;
0241             break;
0242         default:
0243             rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
0244                 "switch case %#x not processed\n", boxnum);
0245             break;
0246         }
0247 
0248         /* 3. Check if the box content is empty. */
0249         isfw_read = false;
0250         u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
0251 
0252         if (u1b_tmp != 0xea) {
0253             isfw_read = true;
0254         } else {
0255             if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
0256                 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
0257                 rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
0258         }
0259 
0260         if (isfw_read) {
0261             wait_h2c_limmit = 100;
0262             isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
0263             while (!isfw_read) {
0264                 wait_h2c_limmit--;
0265                 if (wait_h2c_limmit == 0) {
0266                     rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0267                         "Waiting too long for FW read clear HMEBox(%d)!!!\n",
0268                         boxnum);
0269                     break;
0270                 }
0271                 udelay(10);
0272                 isfw_read =
0273                   _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
0274                 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
0275                 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0276                     "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
0277                     boxnum, u1b_tmp);
0278             }
0279         }
0280 
0281         /* If Fw has not read the last
0282          * H2C cmd, break and give up this H2C.
0283          */
0284         if (!isfw_read) {
0285             rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0286                 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
0287                 boxnum);
0288             break;
0289         }
0290         /* 4. Fill the H2C cmd into box */
0291         memset(boxcontent, 0, sizeof(boxcontent));
0292         memset(boxextcontent, 0, sizeof(boxextcontent));
0293         boxcontent[0] = element_id;
0294         rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0295             "Write element_id box_reg(%4x) = %2x\n",
0296             box_reg, element_id);
0297 
0298         switch (cmd_len) {
0299         case 1:
0300         case 2:
0301         case 3:
0302             /*boxcontent[0] &= ~(BIT(7));*/
0303             memcpy((u8 *)(boxcontent) + 1,
0304                    cmdbuffer + buf_index, cmd_len);
0305 
0306             for (idx = 0; idx < 4; idx++) {
0307                 rtl_write_byte(rtlpriv, box_reg + idx,
0308                            boxcontent[idx]);
0309             }
0310             break;
0311         case 4:
0312         case 5:
0313         case 6:
0314         case 7:
0315             /*boxcontent[0] |= (BIT(7));*/
0316             memcpy((u8 *)(boxextcontent),
0317                    cmdbuffer + buf_index+3, cmd_len-3);
0318             memcpy((u8 *)(boxcontent) + 1,
0319                    cmdbuffer + buf_index, 3);
0320 
0321             for (idx = 0; idx < 4; idx++) {
0322                 rtl_write_byte(rtlpriv, box_extreg + idx,
0323                            boxextcontent[idx]);
0324             }
0325 
0326             for (idx = 0; idx < 4; idx++) {
0327                 rtl_write_byte(rtlpriv, box_reg + idx,
0328                            boxcontent[idx]);
0329             }
0330             break;
0331         default:
0332             rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
0333                 "switch case %#x not processed\n", cmd_len);
0334             break;
0335         }
0336 
0337         bwrite_sucess = true;
0338 
0339         rtlhal->last_hmeboxnum = boxnum + 1;
0340         if (rtlhal->last_hmeboxnum == 4)
0341             rtlhal->last_hmeboxnum = 0;
0342 
0343         rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0344             "pHalData->last_hmeboxnum  = %d\n",
0345             rtlhal->last_hmeboxnum);
0346     }
0347 
0348     spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
0349     rtlhal->h2c_setinprogress = false;
0350     spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0351 
0352     rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
0353 }
0354 
0355 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
0356               u8 element_id, u32 cmd_len, u8 *cmdbuffer)
0357 {
0358     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0359     u32 tmp_cmdbuf[2];
0360 
0361     if (!rtlhal->fw_ready) {
0362         WARN_ONCE(true,
0363               "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
0364         return;
0365     }
0366 
0367     memset(tmp_cmdbuf, 0, 8);
0368     memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
0369     _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
0370 }
0371 
0372 void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
0373 {
0374     u8 u1b_tmp;
0375     struct rtl_priv *rtlpriv = rtl_priv(hw);
0376 
0377     u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
0378     rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
0379 
0380     u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
0381     rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
0382 
0383     udelay(50);
0384 
0385     u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
0386     rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
0387 
0388     u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
0389     rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
0390 
0391     rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
0392         "  _8051Reset92E(): 8051 reset success .\n");
0393 }
0394 
0395 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
0396 {
0397     struct rtl_priv *rtlpriv = rtl_priv(hw);
0398     u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
0399     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0400     u8 rlbm, power_state = 0, byte5 = 0;
0401     u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
0402     struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
0403     bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
0404                 btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
0405     bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
0406               btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
0407 
0408     if (bt_ctrl_lps)
0409         mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
0410 
0411     rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
0412         mode, bt_ctrl_lps);
0413 
0414     switch (mode) {
0415     case FW_PS_MIN_MODE:
0416         rlbm = 0;
0417         awake_intvl = 2;
0418         break;
0419     case FW_PS_MAX_MODE:
0420         rlbm = 1;
0421         awake_intvl = 2;
0422         break;
0423     case FW_PS_DTIM_MODE:
0424         rlbm = 2;
0425         awake_intvl = ppsc->reg_max_lps_awakeintvl;
0426         /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
0427          * is only used in swlps.
0428          */
0429         break;
0430     default:
0431         rlbm = 2;
0432         awake_intvl = 4;
0433         break;
0434     }
0435 
0436     if (rtlpriv->mac80211.p2p) {
0437         awake_intvl = 2;
0438         rlbm = 1;
0439     }
0440 
0441     if (mode == FW_PS_ACTIVE_MODE) {
0442         byte5 = 0x40;
0443         power_state = FW_PWR_STATE_ACTIVE;
0444     } else {
0445         if (bt_ctrl_lps) {
0446             byte5 = btc_ops->btc_get_lps_val(rtlpriv);
0447             power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
0448 
0449             if ((rlbm == 2) && (byte5 & BIT(4))) {
0450                 /* Keep awake interval to 1 to prevent from
0451                  * decreasing coex performance
0452                  */
0453                 awake_intvl = 2;
0454                 rlbm = 2;
0455             }
0456         } else {
0457             byte5 = 0x40;
0458             power_state = FW_PWR_STATE_RF_OFF;
0459         }
0460     }
0461 
0462     SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
0463     SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
0464     SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
0465                      bt_ctrl_lps ? 0 :
0466                      ((rtlpriv->mac80211.p2p) ?
0467                       ppsc->smart_ps : 1));
0468     SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
0469                            awake_intvl);
0470     SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
0471     SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
0472     SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
0473 
0474     RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
0475               "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
0476               u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
0477     if (rtlpriv->cfg->ops->get_btc_status())
0478         btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
0479                          H2C_92E_PWEMODE_LENGTH);
0480     rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
0481                  u1_h2c_set_pwrmode);
0482 }
0483 
0484 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
0485 {
0486     u8 parm[3] = { 0 , 0 , 0 };
0487     /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
0488      *          bit1=0-->update Media Status to MACID
0489      *          bit1=1-->update Media Status from MACID to MACID_End
0490      * parm[1]: MACID, if this is INFRA_STA, MacID = 0
0491      * parm[2]: MACID_End
0492      */
0493 
0494     SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
0495     SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
0496 
0497     rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
0498 }
0499 
0500 #define BEACON_PG       0 /* ->1 */
0501 #define PSPOLL_PG       2
0502 #define NULL_PG         3
0503 #define PROBERSP_PG     4 /* ->5 */
0504 #define QOS_NULL_PG     6
0505 #define BT_QOS_NULL_PG  7
0506 
0507 #define TOTAL_RESERVED_PKT_LEN  1024
0508 
0509 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
0510     /* page 0 beacon */
0511     0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0512     0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
0513     0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
0514     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0515     0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
0516     0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
0517     0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
0518     0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
0519     0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
0520     0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0521     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0522     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0523     0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
0524     0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
0525     0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
0526     0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
0527 
0528     /* page 1 beacon */
0529     0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
0530     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0531     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0532     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0533     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0534     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0535     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0536     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0537     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0538     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0539     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0540     0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0541     0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
0542     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0543     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0544     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0545 
0546     /* page 2  ps-poll */
0547     0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
0548     0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
0549     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0550     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0551     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0552     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0553     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0554     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0555     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0556     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0557     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0558     0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0559     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0560     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0561     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0562     0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0563 
0564     /* page 3  null */
0565     0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
0566     0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
0567     0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
0568     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0569     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0570     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0571     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0572     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0573     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0574     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0575     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0576     0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0577     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0578     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0579     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0580     0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0581 
0582     /* page 4  probe_resp */
0583     0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
0584     0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0585     0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
0586     0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
0587     0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
0588     0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
0589     0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
0590     0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
0591     0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
0592     0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
0593     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0594     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0595     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0596     0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
0597     0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0598     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0599 
0600     /* page 5  probe_resp */
0601     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0602     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0603     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0604     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0605     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0606     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0607     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0608     0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0609     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0610     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0611     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0612     0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0613 
0614     /* page 6 qos null data */
0615     0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
0616     0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
0617     0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
0618     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0619     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0620     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0621     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0622     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0623     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0624     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0625     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0626     0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0627     0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
0628     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0629     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0630     0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0631 
0632     /* page 7 BT-qos null data */
0633     0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
0634     0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
0635     0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
0636     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0637     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0638     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0639     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0640     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0641     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0642     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0643     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0644     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0645     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0646     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0647     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0648     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0649     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0650     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0651     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0652     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0653 };
0654 
0655 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
0656 {
0657     struct rtl_priv *rtlpriv = rtl_priv(hw);
0658     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0659     struct sk_buff *skb = NULL;
0660     bool rtstatus;
0661     u32 totalpacketlen;
0662     u8 u1rsvdpageloc[5] = { 0 };
0663     bool b_dlok = false;
0664 
0665     u8 *beacon;
0666     u8 *p_pspoll;
0667     u8 *nullfunc;
0668     u8 *p_probersp;
0669     u8 *qosnull;
0670     u8 *btqosnull;
0671     /*---------------------------------------------------------
0672      *          (1) beacon
0673      *---------------------------------------------------------
0674      */
0675     beacon = &reserved_page_packet[BEACON_PG * 128];
0676     SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
0677     SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
0678 
0679     /*-------------------------------------------------------
0680      *          (2) ps-poll
0681      *--------------------------------------------------------
0682      */
0683     p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
0684     SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
0685     SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
0686     SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
0687 
0688     SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
0689 
0690     /*--------------------------------------------------------
0691      *          (3) null data
0692      *---------------------------------------------------------
0693      */
0694     nullfunc = &reserved_page_packet[NULL_PG * 128];
0695     SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
0696     SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
0697     SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
0698 
0699     SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
0700 
0701     /*---------------------------------------------------------
0702      *          (4) probe response
0703      *----------------------------------------------------------
0704      */
0705     p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
0706     SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
0707     SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
0708     SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
0709 
0710     SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
0711 
0712     /*---------------------------------------------------------
0713      *          (5) QoS null data
0714      *----------------------------------------------------------
0715      */
0716     qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
0717     SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
0718     SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
0719     SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
0720 
0721     SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
0722 
0723     /*---------------------------------------------------------
0724      *          (6) BT QoS null data
0725      *----------------------------------------------------------
0726      */
0727     btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
0728     SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
0729     SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
0730     SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
0731 
0732     SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
0733 
0734     totalpacketlen = TOTAL_RESERVED_PKT_LEN;
0735 
0736     RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
0737               "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
0738               &reserved_page_packet[0], totalpacketlen);
0739     RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
0740               "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
0741               u1rsvdpageloc, 3);
0742 
0743     skb = dev_alloc_skb(totalpacketlen);
0744     if (!skb)
0745         return;
0746     skb_put_data(skb, &reserved_page_packet, totalpacketlen);
0747 
0748     rtstatus = rtl_cmd_send_packet(hw, skb);
0749     if (rtstatus)
0750         b_dlok = true;
0751 
0752     if (b_dlok) {
0753         rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
0754             "Set RSVD page location to Fw.\n");
0755         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
0756                   "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
0757         rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
0758                      sizeof(u1rsvdpageloc), u1rsvdpageloc);
0759     } else {
0760         rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
0761             "Set RSVD page location to Fw FAIL!!!!!!.\n");
0762     }
0763 }
0764 
0765 /*Shoud check FW support p2p or not.*/
0766 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
0767 {
0768     u8 u1_ctwindow_period[1] = {ctwindow};
0769 
0770     rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
0771 }
0772 
0773 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
0774 {
0775     struct rtl_priv *rtlpriv = rtl_priv(hw);
0776     struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
0777     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0778     struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
0779     struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
0780     u8 i;
0781     u16 ctwindow;
0782     u32 start_time, tsf_low;
0783 
0784     switch (p2p_ps_state) {
0785     case P2P_PS_DISABLE:
0786         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
0787         memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
0788         break;
0789     case P2P_PS_ENABLE:
0790         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
0791         /* update CTWindow value. */
0792         if (p2pinfo->ctwindow > 0) {
0793             p2p_ps_offload->ctwindow_en = 1;
0794             ctwindow = p2pinfo->ctwindow;
0795             rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
0796         }
0797         /* hw only support 2 set of NoA */
0798         for (i = 0 ; i < p2pinfo->noa_num ; i++) {
0799             /* To control the register setting for which NOA*/
0800             rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
0801             if (i == 0)
0802                 p2p_ps_offload->noa0_en = 1;
0803             else
0804                 p2p_ps_offload->noa1_en = 1;
0805             /* config P2P NoA Descriptor Register */
0806             rtl_write_dword(rtlpriv, 0x5E0,
0807                     p2pinfo->noa_duration[i]);
0808             rtl_write_dword(rtlpriv, 0x5E4,
0809                     p2pinfo->noa_interval[i]);
0810 
0811             /*Get Current TSF value */
0812             tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
0813 
0814             start_time = p2pinfo->noa_start_time[i];
0815             if (p2pinfo->noa_count_type[i] != 1) {
0816                 while (start_time <= (tsf_low + (50 * 1024))) {
0817                     start_time += p2pinfo->noa_interval[i];
0818                     if (p2pinfo->noa_count_type[i] != 255)
0819                         p2pinfo->noa_count_type[i]--;
0820                 }
0821             }
0822             rtl_write_dword(rtlpriv, 0x5E8, start_time);
0823             rtl_write_dword(rtlpriv, 0x5EC,
0824                     p2pinfo->noa_count_type[i]);
0825         }
0826         if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
0827             /* rst p2p circuit */
0828             rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
0829             p2p_ps_offload->offload_en = 1;
0830 
0831             if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
0832                 p2p_ps_offload->role = 1;
0833                 p2p_ps_offload->allstasleep = 0;
0834             } else {
0835                 p2p_ps_offload->role = 0;
0836             }
0837             p2p_ps_offload->discovery = 0;
0838         }
0839         break;
0840     case P2P_PS_SCAN:
0841         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
0842         p2p_ps_offload->discovery = 1;
0843         break;
0844     case P2P_PS_SCAN_DONE:
0845         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
0846         p2p_ps_offload->discovery = 0;
0847         p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
0848         break;
0849     default:
0850         break;
0851     }
0852     rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
0853                  (u8 *)p2p_ps_offload);
0854 }
0855 
0856 void rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
0857                    u8 *cmd_buf, u8 cmd_len)
0858 {
0859     u8 rate = cmd_buf[0] & 0x3F;
0860     bool collision_state = cmd_buf[3] & BIT(0);
0861 
0862     rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
0863 }