1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2012 Realtek Corporation.*/
9 #include "../rtl8192ce/reg.h"
10 #include "../rtl8192ce/def.h"
11 #include "fw_common.h"
12 #include <linux/export.h>
14 static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
16 struct rtl_priv *rtlpriv = rtl_priv(hw);
17 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
19 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
20 u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
22 value32 |= MCUFWDL_EN;
24 value32 &= ~MCUFWDL_EN;
25 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
26 } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
30 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
31 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
34 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
35 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
37 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
38 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
41 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
42 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
44 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
49 static void _rtl92c_write_fw(struct ieee80211_hw *hw,
50 enum version_8192c version, u8 *buffer, u32 size)
52 struct rtl_priv *rtlpriv = rtl_priv(hw);
53 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
55 u8 *bufferptr = (u8 *)buffer;
57 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
58 is_version_b = IS_NORMAL_CHIP(version);
60 u32 pageNums, remainsize;
63 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
64 rtl_fill_dummy(bufferptr, &size);
66 pageNums = size / FW_8192C_PAGE_SIZE;
67 remainsize = size % FW_8192C_PAGE_SIZE;
70 pr_err("Page numbers should not greater then 4\n");
72 for (page = 0; page < pageNums; page++) {
73 offset = page * FW_8192C_PAGE_SIZE;
74 rtl_fw_page_write(hw, page, (bufferptr + offset),
79 offset = pageNums * FW_8192C_PAGE_SIZE;
81 rtl_fw_page_write(hw, page, (bufferptr + offset),
85 rtl_fw_block_write(hw, buffer, size);
89 static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
91 struct rtl_priv *rtlpriv = rtl_priv(hw);
97 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
98 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
99 (!(value32 & FWDL_ChkSum_rpt)));
101 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
102 pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n",
106 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
107 value32 |= MCUFWDL_RDY;
108 value32 &= ~WINTINI_RDY;
109 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
114 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
115 if (value32 & WINTINI_RDY)
118 mdelay(FW_8192C_POLLING_DELAY);
120 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
122 pr_err("Polling FW ready fail! REG_MCUFWDL:0x%08x.\n",
129 int rtl92c_download_fw(struct ieee80211_hw *hw)
131 struct rtl_priv *rtlpriv = rtl_priv(hw);
132 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
133 struct rtlwifi_firmware_header *pfwheader;
137 enum version_8192c version = rtlhal->version;
139 if (!rtlhal->pfirmware)
142 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
143 pfwdata = (u8 *)rtlhal->pfirmware;
144 fwsize = rtlhal->fwsize;
145 if (IS_FW_HEADER_EXIST(pfwheader)) {
146 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
147 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
148 pfwheader->version, pfwheader->signature,
149 (int)sizeof(struct rtlwifi_firmware_header));
151 rtlhal->fw_version = le16_to_cpu(pfwheader->version);
152 rtlhal->fw_subversion = pfwheader->subversion;
153 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
154 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
157 _rtl92c_enable_fw_download(hw, true);
158 _rtl92c_write_fw(hw, version, pfwdata, fwsize);
159 _rtl92c_enable_fw_download(hw, false);
161 err = _rtl92c_fw_free_to_go(hw);
163 pr_err("Firmware is not ready to run!\n");
167 EXPORT_SYMBOL(rtl92c_download_fw);
169 static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
171 struct rtl_priv *rtlpriv = rtl_priv(hw);
172 u8 val_hmetfr, val_mcutst_1;
175 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
176 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
178 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
183 static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
184 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
186 struct rtl_priv *rtlpriv = rtl_priv(hw);
187 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
189 u16 box_reg = 0, box_extreg = 0;
191 bool isfw_read = false;
193 bool bwrite_sucess = false;
194 u8 wait_h2c_limmit = 100;
195 u8 wait_writeh2c_limmit = 100;
196 u8 boxcontent[4], boxextcontent[2];
197 u32 h2c_waitcounter = 0;
201 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
204 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
205 if (rtlhal->h2c_setinprogress) {
206 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
207 "H2C set in progress! Wait to set..element_id(%d).\n",
209 while (rtlhal->h2c_setinprogress) {
210 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
213 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
214 "Wait 100 us (%d times)...\n",
218 if (h2c_waitcounter > 1000)
220 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
223 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
225 rtlhal->h2c_setinprogress = true;
226 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
231 while (!bwrite_sucess) {
232 wait_writeh2c_limmit--;
233 if (wait_writeh2c_limmit == 0) {
234 pr_err("Write H2C fail because no trigger for FW INT!\n");
238 boxnum = rtlhal->last_hmeboxnum;
241 box_reg = REG_HMEBOX_0;
242 box_extreg = REG_HMEBOX_EXT_0;
245 box_reg = REG_HMEBOX_1;
246 box_extreg = REG_HMEBOX_EXT_1;
249 box_reg = REG_HMEBOX_2;
250 box_extreg = REG_HMEBOX_EXT_2;
253 box_reg = REG_HMEBOX_3;
254 box_extreg = REG_HMEBOX_EXT_3;
257 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
258 "switch case %#x not processed\n", boxnum);
262 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
265 if (wait_h2c_limmit == 0) {
266 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
267 "Waiting too long for FW read clear HMEBox(%d)!\n",
274 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
275 u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
276 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
277 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
282 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
283 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
288 memset(boxcontent, 0, sizeof(boxcontent));
289 memset(boxextcontent, 0, sizeof(boxextcontent));
290 boxcontent[0] = element_id;
291 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
292 "Write element_id box_reg(%4x) = %2x\n",
293 box_reg, element_id);
297 boxcontent[0] &= ~(BIT(7));
298 memcpy((u8 *)(boxcontent) + 1,
299 cmdbuffer + buf_index, 1);
301 for (idx = 0; idx < 4; idx++) {
302 rtl_write_byte(rtlpriv, box_reg + idx,
307 boxcontent[0] &= ~(BIT(7));
308 memcpy((u8 *)(boxcontent) + 1,
309 cmdbuffer + buf_index, 2);
311 for (idx = 0; idx < 4; idx++) {
312 rtl_write_byte(rtlpriv, box_reg + idx,
317 boxcontent[0] &= ~(BIT(7));
318 memcpy((u8 *)(boxcontent) + 1,
319 cmdbuffer + buf_index, 3);
321 for (idx = 0; idx < 4; idx++) {
322 rtl_write_byte(rtlpriv, box_reg + idx,
327 boxcontent[0] |= (BIT(7));
328 memcpy((u8 *)(boxextcontent),
329 cmdbuffer + buf_index, 2);
330 memcpy((u8 *)(boxcontent) + 1,
331 cmdbuffer + buf_index + 2, 2);
333 for (idx = 0; idx < 2; idx++) {
334 rtl_write_byte(rtlpriv, box_extreg + idx,
338 for (idx = 0; idx < 4; idx++) {
339 rtl_write_byte(rtlpriv, box_reg + idx,
344 boxcontent[0] |= (BIT(7));
345 memcpy((u8 *)(boxextcontent),
346 cmdbuffer + buf_index, 2);
347 memcpy((u8 *)(boxcontent) + 1,
348 cmdbuffer + buf_index + 2, 3);
350 for (idx = 0; idx < 2; idx++) {
351 rtl_write_byte(rtlpriv, box_extreg + idx,
355 for (idx = 0; idx < 4; idx++) {
356 rtl_write_byte(rtlpriv, box_reg + idx,
361 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
362 "switch case %#x not processed\n", cmd_len);
366 bwrite_sucess = true;
368 rtlhal->last_hmeboxnum = boxnum + 1;
369 if (rtlhal->last_hmeboxnum == 4)
370 rtlhal->last_hmeboxnum = 0;
372 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
373 "pHalData->last_hmeboxnum = %d\n",
374 rtlhal->last_hmeboxnum);
377 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
378 rtlhal->h2c_setinprogress = false;
379 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
381 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
384 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
385 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
387 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
390 if (!rtlhal->fw_ready) {
392 "rtl8192c-common: return H2C cmd because of Fw download fail!!!\n");
396 memset(tmp_cmdbuf, 0, 8);
397 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
398 _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
402 EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
404 void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
408 struct rtl_priv *rtlpriv = rtl_priv(hw);
410 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
411 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
413 while (u1b_tmp & BIT(2)) {
416 WARN_ONCE(true, "rtl8192c-common: 8051 reset fail.\n");
420 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
423 EXPORT_SYMBOL(rtl92c_firmware_selfreset);
425 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
427 struct rtl_priv *rtlpriv = rtl_priv(hw);
428 u8 u1_h2c_set_pwrmode[3] = { 0 };
429 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
431 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
433 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
434 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
435 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
436 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
437 ppsc->reg_max_lps_awakeintvl);
439 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
440 "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
441 u1_h2c_set_pwrmode, 3);
442 rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
444 EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
446 #define BEACON_PG 0 /*->1*/
449 #define PROBERSP_PG 4 /*->5*/
451 #define TOTAL_RESERVED_PKT_LEN 768
453 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
455 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
456 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
457 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
460 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
461 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
462 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
463 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
464 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
465 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
469 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
492 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
505 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
510 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
511 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
523 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 /* page 4 probe_resp */
527 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
528 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
529 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
530 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
531 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
532 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
533 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
534 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
535 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
536 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
537 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
541 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 /* page 5 probe_resp */
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 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,
563 void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
564 bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *))
566 struct rtl_priv *rtlpriv = rtl_priv(hw);
567 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
568 struct sk_buff *skb = NULL;
572 u8 u1rsvdpageloc[3] = { 0 };
579 /*---------------------------------------------------------
581 ---------------------------------------------------------*/
582 beacon = &reserved_page_packet[BEACON_PG * 128];
583 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
584 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
586 /*-------------------------------------------------------
588 --------------------------------------------------------*/
589 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
590 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
591 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
592 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
594 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
596 /*--------------------------------------------------------
598 ---------------------------------------------------------*/
599 nullfunc = &reserved_page_packet[NULL_PG * 128];
600 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
601 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
602 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
604 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
606 /*---------------------------------------------------------
608 ----------------------------------------------------------*/
609 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
610 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
611 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
612 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
614 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
616 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
618 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
619 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
620 &reserved_page_packet[0], totalpacketlen);
621 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
622 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
626 skb = dev_alloc_skb(totalpacketlen);
627 skb_put_data(skb, &reserved_page_packet, totalpacketlen);
630 rtstatus = cmd_send_packet(hw, skb);
632 rtstatus = rtl_cmd_send_packet(hw, skb);
638 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
639 "Set RSVD page location to Fw.\n");
640 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
643 rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
644 sizeof(u1rsvdpageloc), u1rsvdpageloc);
646 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
647 "Set RSVD page location to Fw FAIL!!!!!!.\n");
649 EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
651 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
653 u8 u1_joinbssrpt_parm[1] = { 0 };
655 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
657 rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
659 EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);
661 static void rtl92c_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
663 u8 u1_ctwindow_period[1] = { ctwindow};
665 rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
668 /* refactored routine */
669 static void set_noa_data(struct rtl_priv *rtlpriv,
670 struct rtl_p2p_ps_info *p2pinfo,
671 struct p2p_ps_offload_t *p2p_ps_offload)
674 u32 start_time, tsf_low;
676 /* hw only support 2 set of NoA */
677 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
678 /* To control the reg setting for which NOA*/
679 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
681 p2p_ps_offload->noa0_en = 1;
683 p2p_ps_offload->noa1_en = 1;
685 /* config P2P NoA Descriptor Register */
686 rtl_write_dword(rtlpriv, 0x5E0,
687 p2pinfo->noa_duration[i]);
688 rtl_write_dword(rtlpriv, 0x5E4,
689 p2pinfo->noa_interval[i]);
691 /*Get Current TSF value */
692 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
694 start_time = p2pinfo->noa_start_time[i];
695 if (p2pinfo->noa_count_type[i] != 1) {
696 while (start_time <= (tsf_low+(50*1024))) {
697 start_time += p2pinfo->noa_interval[i];
698 if (p2pinfo->noa_count_type[i] != 255)
699 p2pinfo->noa_count_type[i]--;
702 rtl_write_dword(rtlpriv, 0x5E8, start_time);
703 rtl_write_dword(rtlpriv, 0x5EC,
704 p2pinfo->noa_count_type[i]);
708 void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
710 struct rtl_priv *rtlpriv = rtl_priv(hw);
711 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
712 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
713 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
714 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
717 switch (p2p_ps_state) {
719 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
721 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
724 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
726 /* update CTWindow value. */
727 if (p2pinfo->ctwindow > 0) {
728 p2p_ps_offload->ctwindow_en = 1;
729 ctwindow = p2pinfo->ctwindow;
730 rtl92c_set_p2p_ctw_period_cmd(hw, ctwindow);
732 /* call refactored routine */
733 set_noa_data(rtlpriv, p2pinfo, p2p_ps_offload);
735 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
736 /* rst p2p circuit */
737 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST,
740 p2p_ps_offload->offload_en = 1;
742 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
743 p2p_ps_offload->role = 1;
744 p2p_ps_offload->allstasleep = 0;
746 p2p_ps_offload->role = 0;
749 p2p_ps_offload->discovery = 0;
753 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
754 p2p_ps_offload->discovery = 1;
756 case P2P_PS_SCAN_DONE:
757 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
758 "P2P_PS_SCAN_DONE\n");
759 p2p_ps_offload->discovery = 0;
760 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
766 rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
769 EXPORT_SYMBOL_GPL(rtl92c_set_p2p_ps_offload_cmd);