1 /******************************************************************************
3 * Copyright(c) 2009-2012 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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
26 * Larry Finger <Larry.Finger@lwfinger.net>
28 ****************************************************************************
37 #include "../rtl8723com/fw_common.h"
39 static bool rtl8723ae_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
41 struct rtl_priv *rtlpriv = rtl_priv(hw);
42 u8 val_hmetfr, val_mcutst_1;
45 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
46 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
48 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
53 static void _rtl8723ae_fill_h2c_command(struct ieee80211_hw *hw,
54 u8 element_id, u32 cmd_len,
57 struct rtl_priv *rtlpriv = rtl_priv(hw);
58 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
60 u16 box_reg = 0, box_extreg = 0;
63 bool bwrite_success = false;
64 u8 wait_h2c_limmit = 100;
65 u8 wait_writeh2c_limmit = 100;
66 u8 boxcontent[4], boxextcontent[2];
67 u32 h2c_waitcounter = 0;
71 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
74 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
75 if (rtlhal->h2c_setinprogress) {
76 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
77 "H2C set in progress! Wait to set..element_id(%d).\n",
80 while (rtlhal->h2c_setinprogress) {
81 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
84 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
85 "Wait 100 us (%d times)...\n",
89 if (h2c_waitcounter > 1000)
91 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
94 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
96 rtlhal->h2c_setinprogress = true;
97 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
102 while (!bwrite_success) {
103 wait_writeh2c_limmit--;
104 if (wait_writeh2c_limmit == 0) {
105 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
106 "Write H2C fail because no trigger "
111 boxnum = rtlhal->last_hmeboxnum;
114 box_reg = REG_HMEBOX_0;
115 box_extreg = REG_HMEBOX_EXT_0;
118 box_reg = REG_HMEBOX_1;
119 box_extreg = REG_HMEBOX_EXT_1;
122 box_reg = REG_HMEBOX_2;
123 box_extreg = REG_HMEBOX_EXT_2;
126 box_reg = REG_HMEBOX_3;
127 box_extreg = REG_HMEBOX_EXT_3;
130 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
131 "switch case not processed\n");
135 isfw_rd = rtl8723ae_check_fw_read_last_h2c(hw, boxnum);
139 if (wait_h2c_limmit == 0) {
140 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
141 "Waiting too long for FW read clear HMEBox(%d)!\n",
148 isfw_rd = rtl8723ae_check_fw_read_last_h2c(hw, boxnum);
149 u1tmp = rtl_read_byte(rtlpriv, 0x1BF);
150 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
151 "Waiting for FW read clear HMEBox(%d)!!! "
152 "0x1BF = %2x\n", boxnum, u1tmp);
156 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
157 "Write H2C register BOX[%d] fail!!!!! "
158 "Fw do not read.\n", boxnum);
162 memset(boxcontent, 0, sizeof(boxcontent));
163 memset(boxextcontent, 0, sizeof(boxextcontent));
164 boxcontent[0] = element_id;
165 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
166 "Write element_id box_reg(%4x) = %2x\n",
167 box_reg, element_id);
171 boxcontent[0] &= ~(BIT(7));
172 memcpy((u8 *) (boxcontent) + 1,
175 for (idx = 0; idx < 4; idx++) {
176 rtl_write_byte(rtlpriv, box_reg + idx,
181 boxcontent[0] &= ~(BIT(7));
182 memcpy((u8 *) (boxcontent) + 1,
185 for (idx = 0; idx < 4; idx++) {
186 rtl_write_byte(rtlpriv, box_reg + idx,
191 boxcontent[0] &= ~(BIT(7));
192 memcpy((u8 *) (boxcontent) + 1,
195 for (idx = 0; idx < 4; idx++) {
196 rtl_write_byte(rtlpriv, box_reg + idx,
201 boxcontent[0] |= (BIT(7));
202 memcpy((u8 *) (boxextcontent),
204 memcpy((u8 *) (boxcontent) + 1,
207 for (idx = 0; idx < 2; idx++) {
208 rtl_write_byte(rtlpriv, box_extreg + idx,
212 for (idx = 0; idx < 4; idx++) {
213 rtl_write_byte(rtlpriv, box_reg + idx,
218 boxcontent[0] |= (BIT(7));
219 memcpy((u8 *) (boxextcontent),
221 memcpy((u8 *) (boxcontent) + 1,
224 for (idx = 0; idx < 2; idx++) {
225 rtl_write_byte(rtlpriv, box_extreg + idx,
229 for (idx = 0; idx < 4; idx++) {
230 rtl_write_byte(rtlpriv, box_reg + idx,
235 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
236 "switch case not process\n");
240 bwrite_success = true;
242 rtlhal->last_hmeboxnum = boxnum + 1;
243 if (rtlhal->last_hmeboxnum == 4)
244 rtlhal->last_hmeboxnum = 0;
246 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
247 "pHalData->last_hmeboxnum = %d\n",
248 rtlhal->last_hmeboxnum);
251 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
252 rtlhal->h2c_setinprogress = false;
253 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
255 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
258 void rtl8723ae_fill_h2c_cmd(struct ieee80211_hw *hw,
259 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
261 struct rtl_priv *rtlpriv = rtl_priv(hw);
262 struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
264 if (rtlhal->fw_ready == false) {
266 "return H2C cmd because of Fw download fail!!!\n");
270 _rtl8723ae_fill_h2c_command(hw, element_id, cmd_len, p_cmdbuffer);
274 static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw,
277 struct rtl_priv *rtlpriv = rtl_priv(hw);
278 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
279 struct rtl8192_tx_ring *ring;
280 struct rtl_tx_desc *pdesc;
282 struct sk_buff *pskb = NULL;
284 ring = &rtlpci->tx_ring[BEACON_QUEUE];
286 pskb = __skb_dequeue(&ring->queue);
290 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
292 pdesc = &ring->desc[0];
294 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
296 __skb_queue_tail(&ring->queue, skb);
298 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
300 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
305 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
307 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
308 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
309 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
312 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
313 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
314 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
315 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
316 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
317 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
321 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
344 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
357 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
362 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
363 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
375 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 /* page 4 probe_resp */
379 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
380 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
381 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
382 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
383 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
384 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
385 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
386 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
387 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
388 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
389 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
393 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 /* page 5 probe_resp */
397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
417 struct rtl_priv *rtlpriv = rtl_priv(hw);
418 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
419 struct sk_buff *skb = NULL;
423 u8 u1RsvdPageLoc[3] = { 0 };
430 /*---------------------------------------------------------
432 ---------------------------------------------------------
434 beacon = &reserved_page_packet[BEACON_PG * 128];
435 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
436 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
438 /*-------------------------------------------------------
440 --------------------------------------------------------
442 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
443 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
444 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
445 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
447 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
449 /*--------------------------------------------------------
451 ---------------------------------------------------------i
453 nullfunc = &reserved_page_packet[NULL_PG * 128];
454 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
455 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
456 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
458 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
460 /*---------------------------------------------------------
462 ----------------------------------------------------------
464 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
465 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
466 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
467 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
469 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
471 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
473 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
474 "rtl8723ae_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
475 &reserved_page_packet[0], totalpacketlen);
476 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
477 "rtl8723ae_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
480 skb = dev_alloc_skb(totalpacketlen);
481 memcpy((u8 *) skb_put(skb, totalpacketlen),
482 &reserved_page_packet, totalpacketlen);
484 rtstatus = _rtl8723ae_cmd_send_packet(hw, skb);
490 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
491 "Set RSVD page location to Fw.\n");
492 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
495 rtl8723ae_fill_h2c_cmd(hw, H2C_RSVDPAGE,
496 sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
498 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
499 "Set RSVD page location to Fw FAIL!!!!!!.\n");
502 void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
504 u8 u1_joinbssrpt_parm[1] = { 0 };
506 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
508 rtl8723ae_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
511 static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
514 u8 u1_ctwindow_period[1] = {ctwindow};
516 rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
519 void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
521 struct rtl_priv *rtlpriv = rtl_priv(hw);
522 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
523 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
524 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
525 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
528 u32 start_time, tsf_low;
530 switch (p2p_ps_state) {
532 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
533 memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t));
536 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
537 /* update CTWindow value. */
538 if (p2pinfo->ctwindow > 0) {
539 p2p_ps_offload->ctwindow_en = 1;
540 ctwindow = p2pinfo->ctwindow;
541 rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow);
544 /* hw only support 2 set of NoA */
545 for (i = 0; i < p2pinfo->noa_num; i++) {
546 /* To control the register setting for which NOA*/
547 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
549 p2p_ps_offload->noa0_en = 1;
551 p2p_ps_offload->noa1_en = 1;
553 /* config P2P NoA Descriptor Register */
554 rtl_write_dword(rtlpriv, 0x5E0,
555 p2pinfo->noa_duration[i]);
556 rtl_write_dword(rtlpriv, 0x5E4,
557 p2pinfo->noa_interval[i]);
559 /*Get Current TSF value */
560 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
562 start_time = p2pinfo->noa_start_time[i];
563 if (p2pinfo->noa_count_type[i] != 1) {
564 while (start_time <= (tsf_low+(50*1024))) {
565 start_time += p2pinfo->noa_interval[i];
566 if (p2pinfo->noa_count_type[i] != 255)
567 p2pinfo->noa_count_type[i]--;
570 rtl_write_dword(rtlpriv, 0x5E8, start_time);
571 rtl_write_dword(rtlpriv, 0x5EC,
572 p2pinfo->noa_count_type[i]);
574 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
575 /* rst p2p circuit */
576 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
578 p2p_ps_offload->offload_en = 1;
579 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
580 p2p_ps_offload->role = 1;
581 p2p_ps_offload->allstasleep = 0;
583 p2p_ps_offload->role = 0;
585 p2p_ps_offload->discovery = 0;
589 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
590 p2p_ps_offload->discovery = 1;
592 case P2P_PS_SCAN_DONE:
593 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
594 p2p_ps_offload->discovery = 0;
595 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
600 rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
603 void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
605 struct rtl_priv *rtlpriv = rtl_priv(hw);
606 u8 u1_h2c_set_pwrmode[3] = { 0 };
607 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
609 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
611 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
612 SET_H2CCMD_PWRMODE_PARM_SMART_PS_23A(u1_h2c_set_pwrmode,
613 (rtlpriv->mac80211.p2p) ?
615 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
616 ppsc->reg_max_lps_awakeintvl);
618 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
619 "rtl8723ae_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
620 u1_h2c_set_pwrmode, 3);
621 rtl8723ae_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);