0001
0002
0003
0004 #include "../wifi.h"
0005 #include "../pci.h"
0006 #include "../base.h"
0007 #include "../core.h"
0008 #include "../efuse.h"
0009 #include "../rtl8192ce/reg.h"
0010 #include "../rtl8192ce/def.h"
0011 #include "fw_common.h"
0012 #include <linux/export.h>
0013
0014 static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
0015 {
0016 struct rtl_priv *rtlpriv = rtl_priv(hw);
0017 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0018
0019 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
0020 u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
0021
0022 if (enable)
0023 value32 |= MCUFWDL_EN;
0024 else
0025 value32 &= ~MCUFWDL_EN;
0026 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
0027 } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
0028 u8 tmp;
0029
0030 if (enable) {
0031 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
0032 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
0033 tmp | 0x04);
0034
0035 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
0036 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
0037
0038 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
0039 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
0040 } else {
0041 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
0042 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
0043
0044 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
0045 }
0046 }
0047 }
0048
0049 static void _rtl92c_write_fw(struct ieee80211_hw *hw,
0050 enum version_8192c version, u8 *buffer, u32 size)
0051 {
0052 struct rtl_priv *rtlpriv = rtl_priv(hw);
0053 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0054 bool is_version_b;
0055 u8 *bufferptr = (u8 *)buffer;
0056
0057 rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
0058 is_version_b = IS_NORMAL_CHIP(version);
0059 if (is_version_b) {
0060 u32 pagenums, remainsize;
0061 u32 page, offset;
0062
0063 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
0064 rtl_fill_dummy(bufferptr, &size);
0065
0066 pagenums = size / FW_8192C_PAGE_SIZE;
0067 remainsize = size % FW_8192C_PAGE_SIZE;
0068
0069 if (pagenums > 4)
0070 pr_err("Page numbers should not greater then 4\n");
0071
0072 for (page = 0; page < pagenums; page++) {
0073 offset = page * FW_8192C_PAGE_SIZE;
0074 rtl_fw_page_write(hw, page, (bufferptr + offset),
0075 FW_8192C_PAGE_SIZE);
0076 }
0077
0078 if (remainsize) {
0079 offset = pagenums * FW_8192C_PAGE_SIZE;
0080 page = pagenums;
0081 rtl_fw_page_write(hw, page, (bufferptr + offset),
0082 remainsize);
0083 }
0084 } else {
0085 rtl_fw_block_write(hw, buffer, size);
0086 }
0087 }
0088
0089 static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
0090 {
0091 struct rtl_priv *rtlpriv = rtl_priv(hw);
0092 int err = -EIO;
0093 u32 counter = 0;
0094 u32 value32;
0095
0096 do {
0097 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
0098 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
0099 (!(value32 & FWDL_CHKSUM_RPT)));
0100
0101 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
0102 pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n",
0103 value32);
0104 goto exit;
0105 }
0106 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
0107 value32 |= MCUFWDL_RDY;
0108 value32 &= ~WINTINI_RDY;
0109 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
0110
0111 counter = 0;
0112
0113 do {
0114 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
0115 if (value32 & WINTINI_RDY)
0116 return 0;
0117
0118 mdelay(FW_8192C_POLLING_DELAY);
0119
0120 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
0121
0122 pr_err("Polling FW ready fail! REG_MCUFWDL:0x%08x.\n",
0123 value32);
0124
0125 exit:
0126 return err;
0127 }
0128
0129 int rtl92c_download_fw(struct ieee80211_hw *hw)
0130 {
0131 struct rtl_priv *rtlpriv = rtl_priv(hw);
0132 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0133 struct rtlwifi_firmware_header *pfwheader;
0134 u8 *pfwdata;
0135 u32 fwsize;
0136 int err;
0137 enum version_8192c version = rtlhal->version;
0138
0139 if (!rtlhal->pfirmware)
0140 return 1;
0141
0142 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
0143 pfwdata = (u8 *)rtlhal->pfirmware;
0144 fwsize = rtlhal->fwsize;
0145 if (IS_FW_HEADER_EXIST(pfwheader)) {
0146 rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
0147 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
0148 pfwheader->version, pfwheader->signature,
0149 (int)sizeof(struct rtlwifi_firmware_header));
0150
0151 rtlhal->fw_version = le16_to_cpu(pfwheader->version);
0152 rtlhal->fw_subversion = pfwheader->subversion;
0153 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
0154 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
0155 }
0156
0157 _rtl92c_enable_fw_download(hw, true);
0158 _rtl92c_write_fw(hw, version, pfwdata, fwsize);
0159 _rtl92c_enable_fw_download(hw, false);
0160
0161 err = _rtl92c_fw_free_to_go(hw);
0162 if (err)
0163 pr_err("Firmware is not ready to run!\n");
0164
0165 return 0;
0166 }
0167 EXPORT_SYMBOL(rtl92c_download_fw);
0168
0169 static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
0170 {
0171 struct rtl_priv *rtlpriv = rtl_priv(hw);
0172 u8 val_hmetfr, val_mcutst_1;
0173 bool result = false;
0174
0175 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
0176 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
0177
0178 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
0179 result = true;
0180 return result;
0181 }
0182
0183 static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
0184 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
0185 {
0186 struct rtl_priv *rtlpriv = rtl_priv(hw);
0187 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0188 u8 boxnum;
0189 u16 box_reg = 0, box_extreg = 0;
0190 u8 u1b_tmp;
0191 bool isfw_read = false;
0192 u8 buf_index = 0;
0193 bool bwrite_sucess = false;
0194 u8 wait_h2c_limmit = 100;
0195 u8 wait_writeh2c_limmit = 100;
0196 u8 boxcontent[4], boxextcontent[2];
0197 u32 h2c_waitcounter = 0;
0198 unsigned long flag;
0199 u8 idx;
0200
0201 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
0202
0203 while (true) {
0204 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
0205 if (rtlhal->h2c_setinprogress) {
0206 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0207 "H2C set in progress! Wait to set..element_id(%d).\n",
0208 element_id);
0209 while (rtlhal->h2c_setinprogress) {
0210 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
0211 flag);
0212 h2c_waitcounter++;
0213 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0214 "Wait 100 us (%d times)...\n",
0215 h2c_waitcounter);
0216 udelay(100);
0217
0218 if (h2c_waitcounter > 1000)
0219 return;
0220 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
0221 flag);
0222 }
0223 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0224 } else {
0225 rtlhal->h2c_setinprogress = true;
0226 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0227 break;
0228 }
0229 }
0230
0231 while (!bwrite_sucess) {
0232 wait_writeh2c_limmit--;
0233 if (wait_writeh2c_limmit == 0) {
0234 pr_err("Write H2C fail because no trigger for FW INT!\n");
0235 break;
0236 }
0237
0238 boxnum = rtlhal->last_hmeboxnum;
0239 switch (boxnum) {
0240 case 0:
0241 box_reg = REG_HMEBOX_0;
0242 box_extreg = REG_HMEBOX_EXT_0;
0243 break;
0244 case 1:
0245 box_reg = REG_HMEBOX_1;
0246 box_extreg = REG_HMEBOX_EXT_1;
0247 break;
0248 case 2:
0249 box_reg = REG_HMEBOX_2;
0250 box_extreg = REG_HMEBOX_EXT_2;
0251 break;
0252 case 3:
0253 box_reg = REG_HMEBOX_3;
0254 box_extreg = REG_HMEBOX_EXT_3;
0255 break;
0256 default:
0257 rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
0258 "switch case %#x not processed\n", boxnum);
0259 break;
0260 }
0261
0262 isfw_read = _rtl92c_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
0272 udelay(10);
0273
0274 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
0275 u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
0276 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0277 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
0278 boxnum, u1b_tmp);
0279 }
0280
0281 if (!isfw_read) {
0282 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0283 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
0284 boxnum);
0285 break;
0286 }
0287
0288 memset(boxcontent, 0, sizeof(boxcontent));
0289 memset(boxextcontent, 0, sizeof(boxextcontent));
0290 boxcontent[0] = element_id;
0291 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0292 "Write element_id box_reg(%4x) = %2x\n",
0293 box_reg, element_id);
0294
0295 switch (cmd_len) {
0296 case 1:
0297 boxcontent[0] &= ~(BIT(7));
0298 memcpy((u8 *)(boxcontent) + 1,
0299 cmdbuffer + buf_index, 1);
0300
0301 for (idx = 0; idx < 4; idx++) {
0302 rtl_write_byte(rtlpriv, box_reg + idx,
0303 boxcontent[idx]);
0304 }
0305 break;
0306 case 2:
0307 boxcontent[0] &= ~(BIT(7));
0308 memcpy((u8 *)(boxcontent) + 1,
0309 cmdbuffer + buf_index, 2);
0310
0311 for (idx = 0; idx < 4; idx++) {
0312 rtl_write_byte(rtlpriv, box_reg + idx,
0313 boxcontent[idx]);
0314 }
0315 break;
0316 case 3:
0317 boxcontent[0] &= ~(BIT(7));
0318 memcpy((u8 *)(boxcontent) + 1,
0319 cmdbuffer + buf_index, 3);
0320
0321 for (idx = 0; idx < 4; idx++) {
0322 rtl_write_byte(rtlpriv, box_reg + idx,
0323 boxcontent[idx]);
0324 }
0325 break;
0326 case 4:
0327 boxcontent[0] |= (BIT(7));
0328 memcpy((u8 *)(boxextcontent),
0329 cmdbuffer + buf_index, 2);
0330 memcpy((u8 *)(boxcontent) + 1,
0331 cmdbuffer + buf_index + 2, 2);
0332
0333 for (idx = 0; idx < 2; idx++) {
0334 rtl_write_byte(rtlpriv, box_extreg + idx,
0335 boxextcontent[idx]);
0336 }
0337
0338 for (idx = 0; idx < 4; idx++) {
0339 rtl_write_byte(rtlpriv, box_reg + idx,
0340 boxcontent[idx]);
0341 }
0342 break;
0343 case 5:
0344 boxcontent[0] |= (BIT(7));
0345 memcpy((u8 *)(boxextcontent),
0346 cmdbuffer + buf_index, 2);
0347 memcpy((u8 *)(boxcontent) + 1,
0348 cmdbuffer + buf_index + 2, 3);
0349
0350 for (idx = 0; idx < 2; idx++) {
0351 rtl_write_byte(rtlpriv, box_extreg + idx,
0352 boxextcontent[idx]);
0353 }
0354
0355 for (idx = 0; idx < 4; idx++) {
0356 rtl_write_byte(rtlpriv, box_reg + idx,
0357 boxcontent[idx]);
0358 }
0359 break;
0360 default:
0361 rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
0362 "switch case %#x not processed\n", cmd_len);
0363 break;
0364 }
0365
0366 bwrite_sucess = true;
0367
0368 rtlhal->last_hmeboxnum = boxnum + 1;
0369 if (rtlhal->last_hmeboxnum == 4)
0370 rtlhal->last_hmeboxnum = 0;
0371
0372 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0373 "pHalData->last_hmeboxnum = %d\n",
0374 rtlhal->last_hmeboxnum);
0375 }
0376
0377 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
0378 rtlhal->h2c_setinprogress = false;
0379 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0380
0381 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
0382 }
0383
0384 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
0385 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
0386 {
0387 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0388 u32 tmp_cmdbuf[2];
0389
0390 if (!rtlhal->fw_ready) {
0391 WARN_ONCE(true,
0392 "rtl8192c-common: return H2C cmd because of Fw download fail!!!\n");
0393 return;
0394 }
0395
0396 memset(tmp_cmdbuf, 0, 8);
0397 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
0398 _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
0399
0400 return;
0401 }
0402 EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
0403
0404 void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
0405 {
0406 u8 u1b_tmp;
0407 u8 delay = 100;
0408 struct rtl_priv *rtlpriv = rtl_priv(hw);
0409
0410 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
0411 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
0412
0413 while (u1b_tmp & BIT(2)) {
0414 delay--;
0415 if (delay == 0) {
0416 WARN_ONCE(true, "rtl8192c-common: 8051 reset fail.\n");
0417 break;
0418 }
0419 udelay(50);
0420 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
0421 }
0422 }
0423 EXPORT_SYMBOL(rtl92c_firmware_selfreset);
0424
0425 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
0426 {
0427 struct rtl_priv *rtlpriv = rtl_priv(hw);
0428 u8 u1_h2c_set_pwrmode[3] = { 0 };
0429 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0430
0431 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
0432
0433 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
0434 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
0435 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
0436 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
0437 ppsc->reg_max_lps_awakeintvl);
0438
0439 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
0440 "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
0441 u1_h2c_set_pwrmode, 3);
0442 rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
0443 }
0444 EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
0445
0446 #define BEACON_PG 0
0447 #define PSPOLL_PG 2
0448 #define NULL_PG 3
0449 #define PROBERSP_PG 4
0450
0451 #define TOTAL_RESERVED_PKT_LEN 768
0452
0453 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
0454
0455 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0456 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0457 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
0458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0459 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
0460 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
0461 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
0462 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
0463 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
0464 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
0465 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0468 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
0469 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0471
0472
0473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0485 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
0486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0487 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0489
0490
0491 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
0492 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0503 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
0504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0505 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0507
0508
0509 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
0510 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0511 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
0512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0521 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
0522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0523 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0525
0526
0527 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
0528 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0529 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
0530 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
0531 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
0532 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
0533 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
0534 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
0535 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
0536 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
0537 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
0541 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0543
0544
0545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0561 };
0562
0563 void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
0564 bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *))
0565 {
0566 struct rtl_priv *rtlpriv = rtl_priv(hw);
0567 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0568 struct sk_buff *skb = NULL;
0569
0570 u32 totalpacketlen;
0571 bool rtstatus;
0572 u8 u1rsvdpageloc[3] = { 0 };
0573 bool b_dlok = false;
0574
0575 u8 *beacon;
0576 u8 *p_pspoll;
0577 u8 *nullfunc;
0578 u8 *p_probersp;
0579
0580
0581
0582 beacon = &reserved_page_packet[BEACON_PG * 128];
0583 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
0584 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
0585
0586
0587
0588
0589 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
0590 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
0591 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
0592 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
0593
0594 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
0595
0596
0597
0598
0599 nullfunc = &reserved_page_packet[NULL_PG * 128];
0600 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
0601 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
0602 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
0603
0604 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
0605
0606
0607
0608
0609 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
0610 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
0611 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
0612 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
0613
0614 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
0615
0616 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
0617
0618 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
0619 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
0620 &reserved_page_packet[0], totalpacketlen);
0621 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
0622 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
0623 u1rsvdpageloc, 3);
0624
0625 skb = dev_alloc_skb(totalpacketlen);
0626 if (!skb)
0627 return;
0628 skb_put_data(skb, &reserved_page_packet, totalpacketlen);
0629
0630 if (cmd_send_packet)
0631 rtstatus = cmd_send_packet(hw, skb);
0632 else
0633 rtstatus = rtl_cmd_send_packet(hw, skb);
0634
0635 if (rtstatus)
0636 b_dlok = true;
0637
0638 if (b_dlok) {
0639 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
0640 "Set RSVD page location to Fw.\n");
0641 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
0642 "H2C_RSVDPAGE:\n",
0643 u1rsvdpageloc, 3);
0644 rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
0645 sizeof(u1rsvdpageloc), u1rsvdpageloc);
0646 } else
0647 rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
0648 "Set RSVD page location to Fw FAIL!!!!!!.\n");
0649 }
0650 EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
0651
0652 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
0653 {
0654 u8 u1_joinbssrpt_parm[1] = { 0 };
0655
0656 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
0657
0658 rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
0659 }
0660 EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);
0661
0662 static void rtl92c_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
0663 {
0664 u8 u1_ctwindow_period[1] = { ctwindow};
0665
0666 rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
0667 }
0668
0669
0670 static void set_noa_data(struct rtl_priv *rtlpriv,
0671 struct rtl_p2p_ps_info *p2pinfo,
0672 struct p2p_ps_offload_t *p2p_ps_offload)
0673 {
0674 int i;
0675 u32 start_time, tsf_low;
0676
0677
0678 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
0679
0680 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
0681 if (i == 0)
0682 p2p_ps_offload->noa0_en = 1;
0683 else
0684 p2p_ps_offload->noa1_en = 1;
0685
0686
0687 rtl_write_dword(rtlpriv, 0x5E0,
0688 p2pinfo->noa_duration[i]);
0689 rtl_write_dword(rtlpriv, 0x5E4,
0690 p2pinfo->noa_interval[i]);
0691
0692
0693 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
0694
0695 start_time = p2pinfo->noa_start_time[i];
0696 if (p2pinfo->noa_count_type[i] != 1) {
0697 while (start_time <= (tsf_low+(50*1024))) {
0698 start_time += p2pinfo->noa_interval[i];
0699 if (p2pinfo->noa_count_type[i] != 255)
0700 p2pinfo->noa_count_type[i]--;
0701 }
0702 }
0703 rtl_write_dword(rtlpriv, 0x5E8, start_time);
0704 rtl_write_dword(rtlpriv, 0x5EC,
0705 p2pinfo->noa_count_type[i]);
0706 }
0707 }
0708
0709 void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
0710 {
0711 struct rtl_priv *rtlpriv = rtl_priv(hw);
0712 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
0713 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0714 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
0715 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
0716 u16 ctwindow;
0717
0718 switch (p2p_ps_state) {
0719 case P2P_PS_DISABLE:
0720 rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
0721 "P2P_PS_DISABLE\n");
0722 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
0723 break;
0724 case P2P_PS_ENABLE:
0725 rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
0726 "P2P_PS_ENABLE\n");
0727
0728 if (p2pinfo->ctwindow > 0) {
0729 p2p_ps_offload->ctwindow_en = 1;
0730 ctwindow = p2pinfo->ctwindow;
0731 rtl92c_set_p2p_ctw_period_cmd(hw, ctwindow);
0732 }
0733
0734 set_noa_data(rtlpriv, p2pinfo, p2p_ps_offload);
0735
0736 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
0737
0738 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST,
0739 BIT(4));
0740
0741 p2p_ps_offload->offload_en = 1;
0742
0743 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
0744 p2p_ps_offload->role = 1;
0745 p2p_ps_offload->allstasleep = 0;
0746 } else {
0747 p2p_ps_offload->role = 0;
0748 }
0749
0750 p2p_ps_offload->discovery = 0;
0751 }
0752 break;
0753 case P2P_PS_SCAN:
0754 rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
0755 p2p_ps_offload->discovery = 1;
0756 break;
0757 case P2P_PS_SCAN_DONE:
0758 rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
0759 "P2P_PS_SCAN_DONE\n");
0760 p2p_ps_offload->discovery = 0;
0761 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
0762 break;
0763 default:
0764 break;
0765 }
0766
0767 rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
0768
0769 }
0770 EXPORT_SYMBOL_GPL(rtl92c_set_p2p_ps_offload_cmd);