linux/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2014  Realtek Corporation.*/
   3
   4#include "../wifi.h"
   5#include "../pci.h"
   6#include "../base.h"
   7#include "../core.h"
   8#include "../efuse.h"
   9#include "reg.h"
  10#include "def.h"
  11#include "fw.h"
  12#include "dm.h"
  13
  14static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
  15{
  16        struct rtl_priv *rtlpriv = rtl_priv(hw);
  17        u8 tmp;
  18
  19        if (enable) {
  20                rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
  21
  22                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
  23                rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
  24        } else {
  25                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  26                rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
  27        }
  28}
  29
  30static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
  31                              enum version_8192e version,
  32                              u8 *buffer, u32 size)
  33{
  34        struct rtl_priv *rtlpriv = rtl_priv(hw);
  35        u8 *bufferptr = (u8 *)buffer;
  36        u32 pagenums, remainsize;
  37        u32 page, offset;
  38
  39        rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
  40
  41        rtl_fill_dummy(bufferptr, &size);
  42
  43        pagenums = size / FW_8192C_PAGE_SIZE;
  44        remainsize = size % FW_8192C_PAGE_SIZE;
  45
  46        if (pagenums > 8)
  47                pr_err("Page numbers should not greater then 8\n");
  48
  49        for (page = 0; page < pagenums; page++) {
  50                offset = page * FW_8192C_PAGE_SIZE;
  51                rtl_fw_page_write(hw, page, (bufferptr + offset),
  52                                  FW_8192C_PAGE_SIZE);
  53                udelay(2);
  54        }
  55
  56        if (remainsize) {
  57                offset = pagenums * FW_8192C_PAGE_SIZE;
  58                page = pagenums;
  59                rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
  60        }
  61}
  62
  63static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
  64{
  65        struct rtl_priv *rtlpriv = rtl_priv(hw);
  66        int err = -EIO;
  67        u32 counter = 0;
  68        u32 value32;
  69
  70        do {
  71                value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  72        } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
  73                 (!(value32 & FWDL_CHKSUM_RPT)));
  74
  75        if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
  76                pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
  77                       value32);
  78                goto exit;
  79        }
  80        value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  81        value32 |= MCUFWDL_RDY;
  82        value32 &= ~WINTINI_RDY;
  83        rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
  84
  85        rtl92ee_firmware_selfreset(hw);
  86        counter = 0;
  87
  88        do {
  89                value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  90                if (value32 & WINTINI_RDY)
  91                        return 0;
  92
  93                udelay(FW_8192C_POLLING_DELAY*10);
  94
  95        } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
  96
  97        pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
  98               value32, counter);
  99
 100exit:
 101        return err;
 102}
 103
 104int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
 105{
 106        struct rtl_priv *rtlpriv = rtl_priv(hw);
 107        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 108        struct rtlwifi_firmware_header *pfwheader;
 109        u8 *pfwdata;
 110        u32 fwsize;
 111        enum version_8192e version = rtlhal->version;
 112
 113        if (!rtlhal->pfirmware)
 114                return 1;
 115
 116        pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
 117        rtlhal->fw_version = le16_to_cpu(pfwheader->version);
 118        rtlhal->fw_subversion = pfwheader->subversion;
 119        pfwdata = (u8 *)rtlhal->pfirmware;
 120        fwsize = rtlhal->fwsize;
 121        rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 122                "normal Firmware SIZE %d\n", fwsize);
 123
 124        if (IS_FW_HEADER_EXIST(pfwheader)) {
 125                rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 126                        "Firmware Version(%d), Signature(%#x),Size(%d)\n",
 127                        pfwheader->version, pfwheader->signature,
 128                        (int)sizeof(struct rtlwifi_firmware_header));
 129
 130                pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
 131                fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
 132        } else {
 133                rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 134                        "Firmware no Header, Signature(%#x)\n",
 135                        pfwheader->signature);
 136        }
 137
 138        if (rtlhal->mac_func_enable) {
 139                if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
 140                        rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
 141                        rtl92ee_firmware_selfreset(hw);
 142                }
 143        }
 144        _rtl92ee_enable_fw_download(hw, true);
 145        _rtl92ee_write_fw(hw, version, pfwdata, fwsize);
 146        _rtl92ee_enable_fw_download(hw, false);
 147
 148        return _rtl92ee_fw_free_to_go(hw);
 149}
 150
 151static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
 152{
 153        struct rtl_priv *rtlpriv = rtl_priv(hw);
 154        u8 val_hmetfr;
 155        bool result = false;
 156
 157        val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
 158        if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
 159                result = true;
 160        return result;
 161}
 162
 163static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
 164                                      u32 cmd_len, u8 *cmdbuffer)
 165{
 166        struct rtl_priv *rtlpriv = rtl_priv(hw);
 167        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 168        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 169        u8 boxnum;
 170        u16 box_reg = 0, box_extreg = 0;
 171        u8 u1b_tmp;
 172        bool isfw_read = false;
 173        u8 buf_index = 0;
 174        bool bwrite_sucess = false;
 175        u8 wait_h2c_limmit = 100;
 176        u8 boxcontent[4], boxextcontent[4];
 177        u32 h2c_waitcounter = 0;
 178        unsigned long flag;
 179        u8 idx;
 180
 181        if (ppsc->dot11_psmode != EACTIVE ||
 182            ppsc->inactive_pwrstate == ERFOFF) {
 183                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 184                        "FillH2CCommand8192E(): Return because RF is off!!!\n");
 185                return;
 186        }
 187
 188        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
 189
 190        /* 1. Prevent race condition in setting H2C cmd.
 191         * (copy from MgntActSet_RF_State().)
 192         */
 193        while (true) {
 194                spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 195                if (rtlhal->h2c_setinprogress) {
 196                        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 197                                "H2C set in progress! Wait to set..element_id(%d).\n",
 198                                element_id);
 199
 200                        while (rtlhal->h2c_setinprogress) {
 201                                spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
 202                                                       flag);
 203                                h2c_waitcounter++;
 204                                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 205                                        "Wait 100 us (%d times)...\n",
 206                                        h2c_waitcounter);
 207                                udelay(100);
 208
 209                                if (h2c_waitcounter > 1000)
 210                                        return;
 211                                spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
 212                                                  flag);
 213                        }
 214                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 215                } else {
 216                        rtlhal->h2c_setinprogress = true;
 217                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 218                        break;
 219                }
 220        }
 221
 222        while (!bwrite_sucess) {
 223                /* 2. Find the last BOX number which has been writen. */
 224                boxnum = rtlhal->last_hmeboxnum;
 225                switch (boxnum) {
 226                case 0:
 227                        box_reg = REG_HMEBOX_0;
 228                        box_extreg = REG_HMEBOX_EXT_0;
 229                        break;
 230                case 1:
 231                        box_reg = REG_HMEBOX_1;
 232                        box_extreg = REG_HMEBOX_EXT_1;
 233                        break;
 234                case 2:
 235                        box_reg = REG_HMEBOX_2;
 236                        box_extreg = REG_HMEBOX_EXT_2;
 237                        break;
 238                case 3:
 239                        box_reg = REG_HMEBOX_3;
 240                        box_extreg = REG_HMEBOX_EXT_3;
 241                        break;
 242                default:
 243                        rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
 244                                "switch case %#x not processed\n", boxnum);
 245                        break;
 246                }
 247
 248                /* 3. Check if the box content is empty. */
 249                isfw_read = false;
 250                u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
 251
 252                if (u1b_tmp != 0xea) {
 253                        isfw_read = true;
 254                } else {
 255                        if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
 256                            rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
 257                                rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
 258                }
 259
 260                if (isfw_read) {
 261                        wait_h2c_limmit = 100;
 262                        isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
 263                        while (!isfw_read) {
 264                                wait_h2c_limmit--;
 265                                if (wait_h2c_limmit == 0) {
 266                                        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 267                                                "Waiting too long for FW read clear HMEBox(%d)!!!\n",
 268                                                boxnum);
 269                                        break;
 270                                }
 271                                udelay(10);
 272                                isfw_read =
 273                                  _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
 274                                u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
 275                                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 276                                        "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
 277                                        boxnum, u1b_tmp);
 278                        }
 279                }
 280
 281                /* If Fw has not read the last
 282                 * H2C cmd, break and give up this H2C.
 283                 */
 284                if (!isfw_read) {
 285                        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 286                                "Write H2C reg BOX[%d] fail,Fw don't read.\n",
 287                                boxnum);
 288                        break;
 289                }
 290                /* 4. Fill the H2C cmd into box */
 291                memset(boxcontent, 0, sizeof(boxcontent));
 292                memset(boxextcontent, 0, sizeof(boxextcontent));
 293                boxcontent[0] = element_id;
 294                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 295                        "Write element_id box_reg(%4x) = %2x\n",
 296                        box_reg, element_id);
 297
 298                switch (cmd_len) {
 299                case 1:
 300                case 2:
 301                case 3:
 302                        /*boxcontent[0] &= ~(BIT(7));*/
 303                        memcpy((u8 *)(boxcontent) + 1,
 304                               cmdbuffer + buf_index, cmd_len);
 305
 306                        for (idx = 0; idx < 4; idx++) {
 307                                rtl_write_byte(rtlpriv, box_reg + idx,
 308                                               boxcontent[idx]);
 309                        }
 310                        break;
 311                case 4:
 312                case 5:
 313                case 6:
 314                case 7:
 315                        /*boxcontent[0] |= (BIT(7));*/
 316                        memcpy((u8 *)(boxextcontent),
 317                               cmdbuffer + buf_index+3, cmd_len-3);
 318                        memcpy((u8 *)(boxcontent) + 1,
 319                               cmdbuffer + buf_index, 3);
 320
 321                        for (idx = 0; idx < 4; idx++) {
 322                                rtl_write_byte(rtlpriv, box_extreg + idx,
 323                                               boxextcontent[idx]);
 324                        }
 325
 326                        for (idx = 0; idx < 4; idx++) {
 327                                rtl_write_byte(rtlpriv, box_reg + idx,
 328                                               boxcontent[idx]);
 329                        }
 330                        break;
 331                default:
 332                        rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
 333                                "switch case %#x not processed\n", cmd_len);
 334                        break;
 335                }
 336
 337                bwrite_sucess = true;
 338
 339                rtlhal->last_hmeboxnum = boxnum + 1;
 340                if (rtlhal->last_hmeboxnum == 4)
 341                        rtlhal->last_hmeboxnum = 0;
 342
 343                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 344                        "pHalData->last_hmeboxnum  = %d\n",
 345                        rtlhal->last_hmeboxnum);
 346        }
 347
 348        spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 349        rtlhal->h2c_setinprogress = false;
 350        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 351
 352        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
 353}
 354
 355void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
 356                          u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 357{
 358        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 359        u32 tmp_cmdbuf[2];
 360
 361        if (!rtlhal->fw_ready) {
 362                WARN_ONCE(true,
 363                          "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
 364                return;
 365        }
 366
 367        memset(tmp_cmdbuf, 0, 8);
 368        memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 369        _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
 370}
 371
 372void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
 373{
 374        u8 u1b_tmp;
 375        struct rtl_priv *rtlpriv = rtl_priv(hw);
 376
 377        u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
 378        rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
 379
 380        u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
 381        rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
 382
 383        udelay(50);
 384
 385        u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
 386        rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
 387
 388        u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
 389        rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
 390
 391        rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
 392                "  _8051Reset92E(): 8051 reset success .\n");
 393}
 394
 395void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
 396{
 397        struct rtl_priv *rtlpriv = rtl_priv(hw);
 398        u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
 399        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 400        u8 rlbm, power_state = 0, byte5 = 0;
 401        u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
 402        struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
 403        bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
 404                            btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
 405        bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
 406                          btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
 407
 408        if (bt_ctrl_lps)
 409                mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
 410
 411        rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
 412                mode, bt_ctrl_lps);
 413
 414        switch (mode) {
 415        case FW_PS_MIN_MODE:
 416                rlbm = 0;
 417                awake_intvl = 2;
 418                break;
 419        case FW_PS_MAX_MODE:
 420                rlbm = 1;
 421                awake_intvl = 2;
 422                break;
 423        case FW_PS_DTIM_MODE:
 424                rlbm = 2;
 425                awake_intvl = ppsc->reg_max_lps_awakeintvl;
 426                /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
 427                 * is only used in swlps.
 428                 */
 429                break;
 430        default:
 431                rlbm = 2;
 432                awake_intvl = 4;
 433                break;
 434        }
 435
 436        if (rtlpriv->mac80211.p2p) {
 437                awake_intvl = 2;
 438                rlbm = 1;
 439        }
 440
 441        if (mode == FW_PS_ACTIVE_MODE) {
 442                byte5 = 0x40;
 443                power_state = FW_PWR_STATE_ACTIVE;
 444        } else {
 445                if (bt_ctrl_lps) {
 446                        byte5 = btc_ops->btc_get_lps_val(rtlpriv);
 447                        power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
 448
 449                        if ((rlbm == 2) && (byte5 & BIT(4))) {
 450                                /* Keep awake interval to 1 to prevent from
 451                                 * decreasing coex performance
 452                                 */
 453                                awake_intvl = 2;
 454                                rlbm = 2;
 455                        }
 456                } else {
 457                        byte5 = 0x40;
 458                        power_state = FW_PWR_STATE_RF_OFF;
 459                }
 460        }
 461
 462        SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
 463        SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
 464        SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
 465                                         bt_ctrl_lps ? 0 :
 466                                         ((rtlpriv->mac80211.p2p) ?
 467                                          ppsc->smart_ps : 1));
 468        SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
 469                                               awake_intvl);
 470        SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
 471        SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
 472        SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
 473
 474        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 475                      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
 476                      u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
 477        if (rtlpriv->cfg->ops->get_btc_status())
 478                btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
 479                                             H2C_92E_PWEMODE_LENGTH);
 480        rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
 481                             u1_h2c_set_pwrmode);
 482}
 483
 484void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
 485{
 486        u8 parm[3] = { 0 , 0 , 0 };
 487        /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
 488         *          bit1=0-->update Media Status to MACID
 489         *          bit1=1-->update Media Status from MACID to MACID_End
 490         * parm[1]: MACID, if this is INFRA_STA, MacID = 0
 491         * parm[2]: MACID_End
 492         */
 493
 494        SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
 495        SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
 496
 497        rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
 498}
 499
 500#define BEACON_PG               0 /* ->1 */
 501#define PSPOLL_PG               2
 502#define NULL_PG                 3
 503#define PROBERSP_PG             4 /* ->5 */
 504#define QOS_NULL_PG             6
 505#define BT_QOS_NULL_PG  7
 506
 507#define TOTAL_RESERVED_PKT_LEN  1024
 508
 509static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
 510        /* page 0 beacon */
 511        0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 512        0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 513        0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
 514        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 515        0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
 516        0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
 517        0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
 518        0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
 519        0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
 520        0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
 521        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 522        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 523        0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
 524        0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
 525        0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
 526        0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
 527
 528        /* page 1 beacon */
 529        0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
 530        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 531        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 532        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 533        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 534        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 535        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 536        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 537        0x00, 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        0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 541        0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
 542        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 543        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 544        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 545
 546        /* page 2  ps-poll */
 547        0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
 548        0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 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        0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 559        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 560        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 561        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 562        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 563
 564        /* page 3  null */
 565        0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
 566        0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 567        0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
 568        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 569        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 570        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 571        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 572        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 573        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 574        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 575        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 576        0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 577        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 578        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 579        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 580        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 581
 582        /* page 4  probe_resp */
 583        0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 584        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 585        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 586        0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
 587        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 588        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 589        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 590        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 591        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 592        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 593        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 594        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 595        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 596        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 597        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 598        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 599
 600        /* page 5  probe_resp */
 601        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 602        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 603        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 604        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 605        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 606        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 607        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 608        0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 609        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 610        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 611        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 612        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 613
 614        /* page 6 qos null data */
 615        0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
 616        0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
 617        0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
 618        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 619        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 620        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 621        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 622        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 623        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 624        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 625        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 626        0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 627        0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
 628        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 629        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 630        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 631
 632        /* page 7 BT-qos null data */
 633        0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
 634        0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
 635        0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
 636        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 637        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 638        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 639        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 640        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 641        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 642        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 643        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 644        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 645        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 646        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 647        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 648        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 649        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 650        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 651        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 652        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 653};
 654
 655void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
 656{
 657        struct rtl_priv *rtlpriv = rtl_priv(hw);
 658        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 659        struct sk_buff *skb = NULL;
 660        bool rtstatus;
 661        u32 totalpacketlen;
 662        u8 u1rsvdpageloc[5] = { 0 };
 663        bool b_dlok = false;
 664
 665        u8 *beacon;
 666        u8 *p_pspoll;
 667        u8 *nullfunc;
 668        u8 *p_probersp;
 669        u8 *qosnull;
 670        u8 *btqosnull;
 671        /*---------------------------------------------------------
 672         *                      (1) beacon
 673         *---------------------------------------------------------
 674         */
 675        beacon = &reserved_page_packet[BEACON_PG * 128];
 676        SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
 677        SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
 678
 679        /*-------------------------------------------------------
 680         *                      (2) ps-poll
 681         *--------------------------------------------------------
 682         */
 683        p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
 684        SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
 685        SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
 686        SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
 687
 688        SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
 689
 690        /*--------------------------------------------------------
 691         *                      (3) null data
 692         *---------------------------------------------------------
 693         */
 694        nullfunc = &reserved_page_packet[NULL_PG * 128];
 695        SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
 696        SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
 697        SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
 698
 699        SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
 700
 701        /*---------------------------------------------------------
 702         *                      (4) probe response
 703         *----------------------------------------------------------
 704         */
 705        p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
 706        SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
 707        SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
 708        SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
 709
 710        SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
 711
 712        /*---------------------------------------------------------
 713         *                      (5) QoS null data
 714         *----------------------------------------------------------
 715         */
 716        qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
 717        SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
 718        SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
 719        SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
 720
 721        SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
 722
 723        /*---------------------------------------------------------
 724         *                      (6) BT QoS null data
 725         *----------------------------------------------------------
 726         */
 727        btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
 728        SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
 729        SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
 730        SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
 731
 732        SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
 733
 734        totalpacketlen = TOTAL_RESERVED_PKT_LEN;
 735
 736        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
 737                      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 738                      &reserved_page_packet[0], totalpacketlen);
 739        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
 740                      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 741                      u1rsvdpageloc, 3);
 742
 743        skb = dev_alloc_skb(totalpacketlen);
 744        if (!skb)
 745                return;
 746        skb_put_data(skb, &reserved_page_packet, totalpacketlen);
 747
 748        rtstatus = rtl_cmd_send_packet(hw, skb);
 749        if (rtstatus)
 750                b_dlok = true;
 751
 752        if (b_dlok) {
 753                rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
 754                        "Set RSVD page location to Fw.\n");
 755                RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
 756                              "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
 757                rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
 758                                     sizeof(u1rsvdpageloc), u1rsvdpageloc);
 759        } else {
 760                rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
 761                        "Set RSVD page location to Fw FAIL!!!!!!.\n");
 762        }
 763}
 764
 765/*Shoud check FW support p2p or not.*/
 766static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
 767{
 768        u8 u1_ctwindow_period[1] = {ctwindow};
 769
 770        rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
 771}
 772
 773void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
 774{
 775        struct rtl_priv *rtlpriv = rtl_priv(hw);
 776        struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
 777        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 778        struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
 779        struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
 780        u8 i;
 781        u16 ctwindow;
 782        u32 start_time, tsf_low;
 783
 784        switch (p2p_ps_state) {
 785        case P2P_PS_DISABLE:
 786                rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
 787                memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
 788                break;
 789        case P2P_PS_ENABLE:
 790                rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
 791                /* update CTWindow value. */
 792                if (p2pinfo->ctwindow > 0) {
 793                        p2p_ps_offload->ctwindow_en = 1;
 794                        ctwindow = p2pinfo->ctwindow;
 795                        rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
 796                }
 797                /* hw only support 2 set of NoA */
 798                for (i = 0 ; i < p2pinfo->noa_num ; i++) {
 799                        /* To control the register setting for which NOA*/
 800                        rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
 801                        if (i == 0)
 802                                p2p_ps_offload->noa0_en = 1;
 803                        else
 804                                p2p_ps_offload->noa1_en = 1;
 805                        /* config P2P NoA Descriptor Register */
 806                        rtl_write_dword(rtlpriv, 0x5E0,
 807                                        p2pinfo->noa_duration[i]);
 808                        rtl_write_dword(rtlpriv, 0x5E4,
 809                                        p2pinfo->noa_interval[i]);
 810
 811                        /*Get Current TSF value */
 812                        tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
 813
 814                        start_time = p2pinfo->noa_start_time[i];
 815                        if (p2pinfo->noa_count_type[i] != 1) {
 816                                while (start_time <= (tsf_low + (50 * 1024))) {
 817                                        start_time += p2pinfo->noa_interval[i];
 818                                        if (p2pinfo->noa_count_type[i] != 255)
 819                                                p2pinfo->noa_count_type[i]--;
 820                                }
 821                        }
 822                        rtl_write_dword(rtlpriv, 0x5E8, start_time);
 823                        rtl_write_dword(rtlpriv, 0x5EC,
 824                                        p2pinfo->noa_count_type[i]);
 825                }
 826                if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
 827                        /* rst p2p circuit */
 828                        rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
 829                        p2p_ps_offload->offload_en = 1;
 830
 831                        if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
 832                                p2p_ps_offload->role = 1;
 833                                p2p_ps_offload->allstasleep = 0;
 834                        } else {
 835                                p2p_ps_offload->role = 0;
 836                        }
 837                        p2p_ps_offload->discovery = 0;
 838                }
 839                break;
 840        case P2P_PS_SCAN:
 841                rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
 842                p2p_ps_offload->discovery = 1;
 843                break;
 844        case P2P_PS_SCAN_DONE:
 845                rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
 846                p2p_ps_offload->discovery = 0;
 847                p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
 848                break;
 849        default:
 850                break;
 851        }
 852        rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
 853                             (u8 *)p2p_ps_offload);
 854}
 855
 856void rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
 857                                   u8 *cmd_buf, u8 cmd_len)
 858{
 859        u8 rate = cmd_buf[0] & 0x3F;
 860        bool collision_state = cmd_buf[3] & BIT(0);
 861
 862        rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
 863}
 864