--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8822B_DEF_H__
+#define __RTL8822B_DEF_H__
+
+#define RX_DESC_NUM_8822BE     512
+
+#define HAL_PRIME_CHNL_OFFSET_DONT_CARE        0
+#define HAL_PRIME_CHNL_OFFSET_LOWER    1
+#define HAL_PRIME_CHNL_OFFSET_UPPER    2
+
+#define RX_MPDU_QUEUE  0
+
+#define IS_HT_RATE(_rate) (_rate >= DESC_RATEMCS0)
+#define IS_CCK_RATE(_rate) (_rate >= DESC_RATE1M && _rate <= DESC_RATE11M)
+#define IS_OFDM_RATE(_rate) (_rate >= DESC_RATE6M && _rate <= DESC_RATE54M)
+#define IS_1T_RATE(_rate)                                                      \
+       ((_rate >= DESC_RATE1M && _rate <= DESC_RATEMCS7) ||                   \
+        (_rate >= DESC_RATEVHT1SS_MCS0 && _rate <= DESC_RATEVHT1SS_MCS9))
+#define IS_2T_RATE(_rate)                                                      \
+       ((_rate >= DESC_RATEMCS8 && _rate <= DESC_RATEMCS15) ||                \
+        (_rate >= DESC_RATEVHT2SS_MCS0 && _rate <= DESC_RATEVHT2SS_MCS9))
+
+#define IS_1T_RATESEC(_rs)                                                     \
+       ((_rs == CCK) || (_rs == OFDM) || (_rs == HT_MCS0_MCS7) ||             \
+        (_rs == VHT_1SSMCS0_1SSMCS9))
+#define IS_2T_RATESEC(_rs)                                                     \
+       ((_rs == HT_MCS8_MCS15) || (_rs == VHT_2SSMCS0_2SSMCS9))
+
+enum rx_packet_type {
+       NORMAL_RX,
+       C2H_PACKET,
+};
+
+enum rtl_desc_qsel {
+       QSLT_BK = 0x2,
+       QSLT_BE = 0x0,
+       QSLT_VI = 0x5,
+       QSLT_VO = 0x7,
+       QSLT_BEACON     = 0x10,
+       QSLT_HIGH       = 0x11,
+       QSLT_MGNT       = 0x12,
+       QSLT_CMD        = 0x13,
+};
+
+enum vht_data_sc {
+       VHT_DATA_SC_DONOT_CARE  = 0,
+       VHT_DATA_SC_20_UPPER_OF_80MHZ   = 1,
+       VHT_DATA_SC_20_LOWER_OF_80MHZ   = 2,
+       VHT_DATA_SC_20_UPPERST_OF_80MHZ = 3,
+       VHT_DATA_SC_20_LOWEST_OF_80MHZ  = 4,
+       VHT_DATA_SC_20_RECV1    = 5,
+       VHT_DATA_SC_20_RECV2    = 6,
+       VHT_DATA_SC_20_RECV3    = 7,
+       VHT_DATA_SC_20_RECV4    = 8,
+       VHT_DATA_SC_40_UPPER_OF_80MHZ   = 9,
+       VHT_DATA_SC_40_LOWER_OF_80MHZ   = 10,
+};
+#endif
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "fw.h"
+
+static bool _rtl8822be_check_fw_read_last_h2c(struct ieee80211_hw *hw,
+                                             u8 boxnum)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 val_hmetfr;
+       bool result = false;
+
+       val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR_8822B);
+       if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
+               result = true;
+       return result;
+}
+
+static void _rtl8822be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
+                                       u32 cmd_len, u8 *cmdbuffer)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       u8 boxnum;
+       u16 box_reg = 0, box_extreg = 0;
+       u8 u1b_tmp;
+       bool isfw_read;
+       u8 buf_index = 0;
+       bool bwrite_success = false;
+       u8 wait_h2c_limmit = 100;
+       u8 boxcontent[4], boxextcontent[4];
+       u32 h2c_waitcounter = 0;
+       unsigned long flag;
+       u8 idx;
+
+       /* 1. Prevent race condition in setting H2C cmd.
+        * (copy from MgntActSet_RF_State().)
+        */
+       while (true) {
+               spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+               if (rtlhal->h2c_setinprogress) {
+                       RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+                                "H2C set in progress! wait..H2C_ID=%d.\n",
+                                element_id);
+
+                       while (rtlhal->h2c_setinprogress) {
+                               spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
+                                                      flag);
+                               h2c_waitcounter++;
+                               RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+                                        "Wait 100 us (%d times)...\n",
+                                        h2c_waitcounter);
+                               udelay(100);
+
+                               if (h2c_waitcounter > 1000)
+                                       return;
+                               spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
+                                                 flag);
+                       }
+                       spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+               } else {
+                       rtlhal->h2c_setinprogress = true;
+                       spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+                       break;
+               }
+       }
+
+       while (!bwrite_success) {
+               /* 2. Find the last BOX number which has been writen. */
+               boxnum = rtlhal->last_hmeboxnum;
+               switch (boxnum) {
+               case 0:
+                       box_reg = REG_HMEBOX0_8822B;
+                       box_extreg = REG_HMEBOX_E0_8822B;
+                       break;
+               case 1:
+                       box_reg = REG_HMEBOX1_8822B;
+                       box_extreg = REG_HMEBOX_E1_8822B;
+                       break;
+               case 2:
+                       box_reg = REG_HMEBOX2_8822B;
+                       box_extreg = REG_HMEBOX_E2_8822B;
+                       break;
+               case 3:
+                       box_reg = REG_HMEBOX3_8822B;
+                       box_extreg = REG_HMEBOX_E3_8822B;
+                       break;
+               default:
+                       RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
+                                "switch case not process\n");
+                       break;
+               }
+
+               /* 3. Check if the box content is empty. */
+               u1b_tmp = rtl_read_byte(rtlpriv, REG_CR_8822B);
+
+               if (u1b_tmp == 0xea) {
+                       if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS_8822B) ==
+                                   0xea ||
+                           rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY_8822B) ==
+                                   0xea)
+                               rtl_write_byte(rtlpriv, REG_SYS_CFG1_8822B + 3,
+                                              0xff);
+
+                       RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+                                "REG_CR is unavaliable\n");
+                       break;
+               }
+
+               wait_h2c_limmit = 100;
+               isfw_read = _rtl8822be_check_fw_read_last_h2c(hw, boxnum);
+               while (!isfw_read) {
+                       wait_h2c_limmit--;
+                       if (wait_h2c_limmit == 0) {
+                               RT_TRACE(rtlpriv, COMP_CMD, DBG_WARNING,
+                                        "Wait too long for FW clear MB%d!!!\n",
+                                        boxnum);
+                               break;
+                       }
+                       udelay(10);
+                       isfw_read =
+                               _rtl8822be_check_fw_read_last_h2c(hw, boxnum);
+                       u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
+                       RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+                                "Waiting for FW clear MB%d!!! 0x130 = %2x\n",
+                                boxnum, u1b_tmp);
+               }
+
+               /* If Fw has not read the last H2C cmd,
+                * break and give up this H2C.
+                */
+               if (!isfw_read) {
+                       RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+                                "Write H2C reg BOX[%d] fail,Fw don't read.\n",
+                                boxnum);
+                       break;
+               }
+               /* 4. Fill the H2C cmd into box */
+               memset(boxcontent, 0, sizeof(boxcontent));
+               memset(boxextcontent, 0, sizeof(boxextcontent));
+               boxcontent[0] = element_id;
+               RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+                        "Write element_id box_reg(%4x) = %2x\n", box_reg,
+                        element_id);
+
+               switch (cmd_len) {
+               case 1:
+               case 2:
+               case 3:
+                       /*boxcontent[0] &= ~(BIT(7));*/
+                       memcpy((u8 *)(boxcontent) + 1, cmdbuffer + buf_index,
+                              cmd_len);
+
+                       for (idx = 0; idx < 4; idx++) {
+                               rtl_write_byte(rtlpriv, box_reg + idx,
+                                              boxcontent[idx]);
+                       }
+                       break;
+               case 4:
+               case 5:
+               case 6:
+               case 7:
+                       /*boxcontent[0] |= (BIT(7));*/
+                       memcpy((u8 *)(boxextcontent), cmdbuffer + buf_index + 3,
+                              cmd_len - 3);
+                       memcpy((u8 *)(boxcontent) + 1, cmdbuffer + buf_index,
+                              3);
+
+                       for (idx = 0; idx < 4; idx++) {
+                               rtl_write_byte(rtlpriv, box_extreg + idx,
+                                              boxextcontent[idx]);
+                       }
+
+                       for (idx = 0; idx < 4; idx++) {
+                               rtl_write_byte(rtlpriv, box_reg + idx,
+                                              boxcontent[idx]);
+                       }
+                       break;
+               default:
+                       RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
+                                "switch case not process\n");
+                       break;
+               }
+
+               bwrite_success = true;
+
+               rtlhal->last_hmeboxnum = boxnum + 1;
+               if (rtlhal->last_hmeboxnum == 4)
+                       rtlhal->last_hmeboxnum = 0;
+
+               RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+                        "pHalData->last_hmeboxnum  = %d\n",
+                        rtlhal->last_hmeboxnum);
+       }
+
+       spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+       rtlhal->h2c_setinprogress = false;
+       spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+
+       RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
+}
+
+void rtl8822be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, u32 cmd_len,
+                           u8 *cmdbuffer)
+{
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 tmp_cmdbuf[8];
+
+       if (!rtlhal->fw_ready) {
+               WARN_ONCE(true,
+                         "return H2C cmd because of Fw download fail!!!\n");
+               return;
+       }
+
+       memset(tmp_cmdbuf, 0, 8);
+       memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
+
+       RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
+                "h2c cmd: len=%d %02X%02X%02X%02X %02X%02X%02X%02X\n", cmd_len,
+                tmp_cmdbuf[2], tmp_cmdbuf[1], tmp_cmdbuf[0], element_id,
+                tmp_cmdbuf[6], tmp_cmdbuf[5], tmp_cmdbuf[4], tmp_cmdbuf[3]);
+
+       _rtl8822be_fill_h2c_command(hw, element_id, cmd_len, tmp_cmdbuf);
+}
+
+void rtl8822be_set_default_port_id_cmd(struct ieee80211_hw *hw)
+{
+       u8 h2c_set_default_port_id[H2C_DEFAULT_PORT_ID_LEN];
+
+       SET_H2CCMD_DFTPID_PORT_ID(h2c_set_default_port_id, 0);
+       SET_H2CCMD_DFTPID_MAC_ID(h2c_set_default_port_id, 0);
+
+       rtl8822be_fill_h2c_cmd(hw, H2C_8822B_DEFAULT_PORT_ID,
+                              H2C_DEFAULT_PORT_ID_LEN,
+                              h2c_set_default_port_id);
+}
+
+void rtl8822be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 u1_h2c_set_pwrmode[H2C_8822B_PWEMODE_LENGTH] = {0};
+       static u8 prev_h2c[H2C_8822B_PWEMODE_LENGTH] = {0};
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+       u8 rlbm, power_state = 0, byte5 = 0;
+       u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
+       u8 smart_ps = 0;
+       struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+       bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+                           btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
+       bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
+                         btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
+
+       memset(u1_h2c_set_pwrmode, 0, H2C_8822B_PWEMODE_LENGTH);
+
+       if (bt_ctrl_lps)
+               mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
+
+       RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+                mode, bt_ctrl_lps);
+
+       switch (mode) {
+       case FW_PS_MIN_MODE:
+               rlbm = 0;
+               awake_intvl = 2;
+               smart_ps = ppsc->smart_ps;
+               break;
+       case FW_PS_MAX_MODE:
+               rlbm = 1;
+               awake_intvl = 2;
+               smart_ps = ppsc->smart_ps;
+               break;
+       case FW_PS_DTIM_MODE:
+               rlbm = 2;
+               awake_intvl = ppsc->reg_max_lps_awakeintvl;
+               /*
+                * hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+                * is only used in swlps.
+                */
+               smart_ps = ppsc->smart_ps;
+               break;
+       case FW_PS_ACTIVE_MODE:
+               rlbm = 0;
+               awake_intvl = 1;
+               break;
+       default:
+               rlbm = 2;
+               awake_intvl = 4;
+               smart_ps = ppsc->smart_ps;
+               break;
+       }
+
+       if (rtlpriv->mac80211.p2p) {
+               awake_intvl = 2;
+               rlbm = 1;
+       }
+
+       if (mode == FW_PS_ACTIVE_MODE) {
+               byte5 = 0x40;
+               power_state = FW_PWR_STATE_ACTIVE;
+       } else {
+               if (bt_ctrl_lps) {
+                       byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+                       power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+                       if ((rlbm == 2) && (byte5 & BIT(4))) {
+                               /* Keep awake interval to 1 to prevent from
+                                * decreasing coex performance
+                                */
+                               awake_intvl = 2;
+                               rlbm = 2;
+                       }
+                       smart_ps = 0;
+               } else {
+                       byte5 = 0x40;
+                       power_state = FW_PWR_STATE_RF_OFF;
+               }
+       }
+
+       SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
+       SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
+       SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, smart_ps);
+       SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, awake_intvl);
+       SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
+       SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
+       SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
+
+       RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+                     "rtl8822be_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
+                     u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH);
+       if (rtlpriv->cfg->ops->get_btc_status())
+               btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
+                                            H2C_8822B_PWEMODE_LENGTH);
+
+       if (!memcmp(prev_h2c, u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH))
+               return;
+       memcpy(prev_h2c, u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH);
+
+       rtl8822be_set_default_port_id_cmd(hw);
+       rtl8822be_fill_h2c_cmd(hw, H2C_8822B_SETPWRMODE,
+                              H2C_8822B_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
+}
+
+void rtl8822be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
+{
+       u8 parm[4] = {0, 0, 0, 0};
+       /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
+        *          bit1=0-->update Media Status to MACID
+        *          bit1=1-->update Media Status from MACID to MACID_End
+        * parm[1]: MACID, if this is INFRA_STA, MacID = 0
+        * parm[2]: MACID_End
+        * parm[3]: bit2-0: port ID
+        */
+
+       SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
+       SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
+
+       rtl8822be_fill_h2c_cmd(hw, H2C_8822B_MSRRPT, 4, parm);
+}
+
+static bool _rtl8822be_send_bcn_or_cmd_packet(struct ieee80211_hw *hw,
+                                             struct sk_buff *skb, u8 hw_queue)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl8192_tx_ring *ring;
+       struct rtl_tx_desc *pdesc;
+       struct rtl_tx_buffer_desc *pbd_desc;
+       unsigned long flags;
+       struct sk_buff *pskb = NULL;
+       u8 *pdesc_or_bddesc;
+       dma_addr_t dma_addr;
+
+       if (hw_queue != BEACON_QUEUE && hw_queue != H2C_QUEUE)
+               return false;
+
+       ring = &rtlpci->tx_ring[hw_queue];
+
+       spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
+
+       if (hw_queue == BEACON_QUEUE) {
+               pdesc = &ring->desc[0];
+               pbd_desc = &ring->buffer_desc[0];
+               pdesc_or_bddesc = (u8 *)pbd_desc;
+
+               /* free previous beacon queue */
+               pskb = __skb_dequeue(&ring->queue);
+
+               if (!pskb)
+                       goto free_prev_skb_done;
+
+               dma_addr = rtlpriv->cfg->ops->get_desc(
+                               hw, (u8 *)pbd_desc, true, HW_DESC_TXBUFF_ADDR);
+
+               pci_unmap_single(rtlpci->pdev, dma_addr, skb->len,
+                                PCI_DMA_TODEVICE);
+               kfree_skb(pskb);
+
+free_prev_skb_done:
+               ;
+
+       } else { /* hw_queue == TXCMD_QUEUE */
+               if (rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) {
+                       RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+                                "get_available_desc fail hw_queue=%d\n",
+                                hw_queue);
+                       spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
+                                              flags);
+                       return false;
+               }
+
+               pdesc = &ring->desc[ring->cur_tx_wp];
+               pbd_desc = &ring->buffer_desc[ring->cur_tx_wp];
+               pdesc_or_bddesc = (u8 *)pdesc;
+       }
+
+       rtlpriv->cfg->ops->fill_tx_special_desc(hw, (u8 *)pdesc, (u8 *)pbd_desc,
+                                               skb, hw_queue);
+
+       __skb_queue_tail(&ring->queue, skb);
+
+       rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc_or_bddesc, true,
+                                   HW_DESC_OWN, (u8 *)&hw_queue);
+
+       spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
+
+       rtlpriv->cfg->ops->tx_polling(hw, hw_queue);
+
+       return true;
+}
+
+bool rtl8822b_halmac_cb_write_data_rsvd_page(struct rtl_priv *rtlpriv, u8 *buf,
+                                            u32 size)
+{
+       struct sk_buff *skb = NULL;
+       u8 u1b_tmp;
+       int count;
+
+       skb = dev_alloc_skb(size);
+       memcpy((u8 *)skb_put(skb, size), buf, size);
+
+       if (!_rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, BEACON_QUEUE))
+               return false;
+
+       /* These code isn't actually need, because halmac will check
+        * BCN_VALID
+        */
+
+       /* Polling Beacon Queue to send Beacon */
+       u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
+       count = 0;
+       while ((count < 20) && (u1b_tmp & BIT(4))) {
+               count++;
+               udelay(10);
+               u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
+       }
+
+       if (count >= 20)
+               pr_err("%s polling beacon fail\n", __func__);
+
+       return true;
+}
+
+bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf,
+                                      u32 size)
+{
+       struct sk_buff *skb = NULL;
+
+       /* without GFP_DMA, pci_map_single() may not work */
+       skb = __netdev_alloc_skb(NULL, size, GFP_ATOMIC | GFP_DMA);
+       memcpy((u8 *)skb_put(skb, size), buf, size);
+
+       return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE);
+}
+
+/* Rsvd page HALMAC_RSVD_DRV_PGNUM_8822B occupies 16 page (2048 byte) */
+#define BEACON_PG      0 /* ->1 */
+#define PSPOLL_PG      2
+#define NULL_PG        3
+#define PROBERSP_PG    4 /* ->5 */
+#define QOS_NULL_PG    6
+#define BT_QOS_NULL_PG 7
+
+#define TOTAL_RESERVED_PKT_LEN 1024
+
+static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {/* page size = 128 */
+       /* page 0 beacon */
+       0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
+       0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
+       0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
+       0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
+       0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
+       0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
+       0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
+       0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
+       0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
+       0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
+
+       /* page 1 beacon */
+       0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+       /* page 2  ps-poll */
+       0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
+       0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x18, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+       /* page 3  null */
+       0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
+       0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
+       0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x72, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+       /* page 4  probe_resp */
+       0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+       0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+       0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+       0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
+       0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+       0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+       0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+       0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+       0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+       0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+       0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+       0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+       /* page 5  probe_resp */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+       /* page 6 qos null data */
+       0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
+       0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+       0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
+       0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+       /* page 7 BT-qos null data */
+       0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
+       0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+       0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       struct sk_buff *skb = NULL;
+
+       u32 totalpacketlen;
+       bool rtstatus;
+       u8 u1_rsvd_page_loc[7] = {0};
+       bool b_dlok = false;
+
+       u8 *beacon;
+       u8 *p_pspoll;
+       u8 *nullfunc;
+       u8 *p_probersp;
+       u8 *qosnull;
+       u8 *btqosnull;
+
+       memset(u1_rsvd_page_loc, 0, sizeof(u1_rsvd_page_loc));
+
+       /*---------------------------------------------------------
+        *                      (1) beacon
+        *---------------------------------------------------------
+        */
+       beacon = &reserved_page_packet[BEACON_PG * 128];
+       SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
+       SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
+
+       /*-------------------------------------------------------
+        *                      (2) ps-poll
+        *--------------------------------------------------------
+        */
+       p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
+       SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
+       SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
+       SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
+
+       SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1_rsvd_page_loc, PSPOLL_PG);
+
+       /*--------------------------------------------------------
+        *                      (3) null data
+        *---------------------------------------------------------
+        */
+       nullfunc = &reserved_page_packet[NULL_PG * 128];
+       SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
+       SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
+       SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
+
+       SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1_rsvd_page_loc, NULL_PG);
+
+       /*---------------------------------------------------------
+        *                      (4) probe response
+        *----------------------------------------------------------
+        */
+       p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
+       SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
+       SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
+       SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
+
+       SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1_rsvd_page_loc, PROBERSP_PG);
+
+       /*---------------------------------------------------------
+        *                      (5) QoS null data
+        *----------------------------------------------------------
+        */
+       qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
+       SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
+       SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
+       SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
+
+       SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1_rsvd_page_loc, QOS_NULL_PG);
+
+       /*---------------------------------------------------------
+        *                      (6) BT QoS null data
+        *----------------------------------------------------------
+        */
+       btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
+       SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
+       SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
+       SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
+
+       SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1_rsvd_page_loc,
+                                                BT_QOS_NULL_PG);
+
+       totalpacketlen = TOTAL_RESERVED_PKT_LEN;
+
+       RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+                     "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+                     &reserved_page_packet[0], totalpacketlen);
+       RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+                     "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+                     u1_rsvd_page_loc, 3);
+
+       skb = dev_alloc_skb(totalpacketlen);
+       memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet,
+              totalpacketlen);
+
+       rtstatus = _rtl8822be_send_bcn_or_cmd_packet(hw, skb, BEACON_QUEUE);
+
+       if (rtstatus)
+               b_dlok = true;
+
+       if (b_dlok) {
+               RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+                        "Set RSVD page location to Fw.\n");
+               RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C_RSVDPAGE:\n",
+                             u1_rsvd_page_loc, 3);
+               rtl8822be_fill_h2c_cmd(hw, H2C_8822B_RSVDPAGE,
+                                      sizeof(u1_rsvd_page_loc),
+                                      u1_rsvd_page_loc);
+       } else
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+                        "Set RSVD page location to Fw FAIL!!!!!!.\n");
+}
+
+/* Should check FW support p2p or not. */
+static void rtl8822be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
+                                            u8 ctwindow)
+{
+       u8 u1_ctwindow_period[1] = {ctwindow};
+
+       rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_CTW_CMD, 1,
+                              u1_ctwindow_period);
+}
+
+void rtl8822be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
+       struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
+       u8 i;
+       u16 ctwindow;
+       u32 start_time, tsf_low;
+
+       switch (p2p_ps_state) {
+       case P2P_PS_DISABLE:
+               RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
+               memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
+               break;
+       case P2P_PS_ENABLE:
+               RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
+               /* update CTWindow value. */
+               if (p2pinfo->ctwindow > 0) {
+                       p2p_ps_offload->ctwindow_en = 1;
+                       ctwindow = p2pinfo->ctwindow;
+                       rtl8822be_set_p2p_ctw_period_cmd(hw, ctwindow);
+               }
+               /* hw only support 2 set of NoA */
+               for (i = 0; i < p2pinfo->noa_num; i++) {
+                       /* To control the register setting for which NOA*/
+                       rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
+                       if (i == 0)
+                               p2p_ps_offload->noa0_en = 1;
+                       else
+                               p2p_ps_offload->noa1_en = 1;
+                       /* config P2P NoA Descriptor Register */
+                       rtl_write_dword(rtlpriv, 0x5E0,
+                                       p2pinfo->noa_duration[i]);
+                       rtl_write_dword(rtlpriv, 0x5E4,
+                                       p2pinfo->noa_interval[i]);
+
+                       /*Get Current TSF value */
+                       tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR_8822B);
+
+                       start_time = p2pinfo->noa_start_time[i];
+                       if (p2pinfo->noa_count_type[i] != 1) {
+                               while (start_time <= (tsf_low + (50 * 1024))) {
+                                       start_time += p2pinfo->noa_interval[i];
+                                       if (p2pinfo->noa_count_type[i] != 255)
+                                               p2pinfo->noa_count_type[i]--;
+                               }
+                       }
+                       rtl_write_dword(rtlpriv, 0x5E8, start_time);
+                       rtl_write_dword(rtlpriv, 0x5EC,
+                                       p2pinfo->noa_count_type[i]);
+               }
+               if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
+                       /* rst p2p circuit */
+                       rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST_8822B, BIT(4));
+                       p2p_ps_offload->offload_en = 1;
+
+                       if (rtlpriv->mac80211.p2p == P2P_ROLE_GO) {
+                               p2p_ps_offload->role = 1;
+                               p2p_ps_offload->allstasleep = 0;
+                       } else {
+                               p2p_ps_offload->role = 0;
+                       }
+                       p2p_ps_offload->discovery = 0;
+               }
+               break;
+       case P2P_PS_SCAN:
+               RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
+               p2p_ps_offload->discovery = 1;
+               break;
+       case P2P_PS_SCAN_DONE:
+               RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
+               p2p_ps_offload->discovery = 0;
+               p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
+               break;
+       default:
+               break;
+       }
+
+       rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_OFFLOAD, 1,
+                              (u8 *)p2p_ps_offload);
+}
+
+static
+void rtl8822be_c2h_content_parsing_ext(struct ieee80211_hw *hw,
+                                      u8 c2h_sub_cmd_id,
+                                      u8 c2h_cmd_len,
+                                      u8 *c2h_content_buf)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_halmac_ops *halmac_ops;
+
+       switch (c2h_sub_cmd_id) {
+       case 0x0F:
+               RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+                        "[C2H], C2H_8822BE_TX_REPORT!\n");
+               rtl_tx_report_handler(hw, c2h_content_buf, c2h_cmd_len);
+               break;
+       default:
+               /* indicate c2h pkt + rx desc to halmac */
+               halmac_ops = rtlpriv->halmac.ops;
+               halmac_ops->halmac_c2h_handle(rtlpriv,
+                                             c2h_content_buf - 24 - 2 - 2,
+                                             c2h_cmd_len + 24 + 2 + 2);
+               break;
+       }
+}
+
+void rtl8822be_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
+                                  u8 c2h_cmd_len, u8 *tmp_buf)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+
+       if (c2h_cmd_id == 0xFF) {
+               rtl8822be_c2h_content_parsing_ext(hw, tmp_buf[0],
+                                                 c2h_cmd_len - 2,
+                                                 tmp_buf + 2);
+               return;
+       }
+
+       switch (c2h_cmd_id) {
+       case C2H_8822B_DBG:
+               RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+                        "[C2H], C2H_8822BE_DBG!!\n");
+               break;
+       case C2H_8822B_TXBF:
+               RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+                        "[C2H], C2H_8822B_TXBF!!\n");
+               break;
+       case C2H_8822B_BT_INFO:
+               RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+                        "[C2H], C2H_8822BE_BT_INFO!!\n");
+               if (rtlpriv->cfg->ops->get_btc_status())
+                       btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
+                                                  c2h_cmd_len);
+               break;
+       case C2H_8822B_BT_MP:
+               RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+                        "[C2H], C2H_8822BE_BT_MP!!\n");
+               if (rtlpriv->cfg->ops->get_btc_status())
+                       btc_ops->btc_btmpinfo_notify(rtlpriv, tmp_buf,
+                                                    c2h_cmd_len);
+               break;
+       default:
+               if (!rtlpriv->phydm.ops->phydm_c2h_content_parsing(
+                           rtlpriv, c2h_cmd_id, c2h_cmd_len, tmp_buf))
+                       break;
+
+               RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+                        "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
+               break;
+       }
+}
+
+void rtl8822be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
+       u8 *tmp_buf = NULL;
+
+       c2h_cmd_id = buffer[0];
+       c2h_cmd_seq = buffer[1];
+       c2h_cmd_len = len - 2;
+       tmp_buf = buffer + 2;
+
+       RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+                "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
+                c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
+
+       RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
+                     "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
+
+       switch (c2h_cmd_id) {
+       case C2H_8822B_BT_INFO:
+       case C2H_8822B_BT_MP:
+               rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
+               break;
+       default:
+               rtl8822be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
+                                             tmp_buf);
+               break;
+       }
+}
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8822B__FW__H__
+#define __RTL8822B__FW__H__
+
+#define USE_OLD_WOWLAN_DEBUG_FW        0
+
+#define H2C_8822B_RSVDPAGE_LOC_LEN     5
+#define H2C_8822B_PWEMODE_LENGTH       7
+#define H2C_8822B_JOINBSSRPT_LENGTH    1
+#define H2C_8822B_AP_OFFLOAD_LENGTH    3
+#define H2C_8822B_WOWLAN_LENGTH        3
+#define H2C_8822B_KEEP_ALIVE_CTRL_LENGTH       3
+#if (USE_OLD_WOWLAN_DEBUG_FW == 0)
+#define H2C_8822B_REMOTE_WAKE_CTRL_LEN 1
+#else
+#define H2C_8822B_REMOTE_WAKE_CTRL_LEN 3
+#endif
+#define H2C_8822B_AOAC_GLOBAL_INFO_LEN 2
+#define H2C_8822B_AOAC_RSVDPAGE_LOC_LEN        7
+#define H2C_DEFAULT_PORT_ID_LEN        2
+
+/* Fw PS state for RPWM.
+ *BIT[2:0] = HW state
+ *BIT[3] = Protocol PS state,  1: register active state, 0: register sleep state
+ *BIT[4] = sub-state
+ */
+#define FW_PS_RF_ON    BIT(2)
+#define FW_PS_REGISTER_ACTIVE  BIT(3)
+
+#define FW_PS_ACK      BIT(6)
+#define FW_PS_TOGGLE   BIT(7)
+
+/* 8822B RPWM value*/
+/* BIT[0] = 1: 32k, 0: 40M*/
+#define FW_PS_CLOCK_OFF        BIT(0) /* 32k */
+#define FW_PS_CLOCK_ON 0 /* 40M */
+
+#define FW_PS_STATE_MASK       (0x0F)
+#define FW_PS_STATE_HW_MASK    (0x07)
+#define FW_PS_STATE_INT_MASK   (0x3F)
+
+#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x))
+
+#define FW_PS_STATE_ALL_ON_8822B       (FW_PS_CLOCK_ON)
+#define FW_PS_STATE_RF_ON_8822B        (FW_PS_CLOCK_ON)
+#define FW_PS_STATE_RF_OFF_8822B       (FW_PS_CLOCK_ON)
+#define FW_PS_STATE_RF_OFF_LOW_PWR     (FW_PS_CLOCK_OFF)
+
+/* For 8822B H2C PwrMode Cmd ID 5.*/
+#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))
+#define FW_PWR_STATE_RF_OFF    0
+
+#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK)
+
+#define IS_IN_LOW_POWER_STATE_8822B(fw_ps_state)                               \
+       (FW_PS_STATE(fw_ps_state) == FW_PS_CLOCK_OFF)
+
+#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))
+#define FW_PWR_STATE_RF_OFF    0
+
+enum rtl8822b_h2c_cmd {
+       H2C_8822B_RSVDPAGE      = 0,
+       H2C_8822B_MSRRPT        = 1,
+       H2C_8822B_SCAN  = 2,
+       H2C_8822B_KEEP_ALIVE_CTRL       = 3,
+       H2C_8822B_DISCONNECT_DECISION   = 4,
+#if (USE_OLD_WOWLAN_DEBUG_FW == 1)
+       H2C_8822B_WO_WLAN       = 5,
+#endif
+       H2C_8822B_INIT_OFFLOAD  = 6,
+#if (USE_OLD_WOWLAN_DEBUG_FW == 1)
+       H2C_8822B_REMOTE_WAKE_CTRL      = 7,
+#endif
+       H2C_8822B_AP_OFFLOAD    = 8,
+       H2C_8822B_BCN_RSVDPAGE  = 9,
+       H2C_8822B_PROBERSP_RSVDPAGE     = 10,
+
+       H2C_8822B_SETPWRMODE    = 0x20,
+       H2C_8822B_PS_TUNING_PARA        = 0x21,
+       H2C_8822B_PS_TUNING_PARA2       = 0x22,
+       H2C_8822B_PS_LPS_PARA   = 0x23,
+       H2C_8822B_P2P_PS_OFFLOAD        = 024,
+       H2C_8822B_DEFAULT_PORT_ID       = 0x2C,
+
+#if (USE_OLD_WOWLAN_DEBUG_FW == 0)
+       H2C_8822B_WO_WLAN       = 0x80,
+       H2C_8822B_REMOTE_WAKE_CTRL      = 0x81,
+       H2C_8822B_AOAC_GLOBAL_INFO      = 0x82,
+       H2C_8822B_AOAC_RSVDPAGE = 0x83,
+#endif
+       H2C_8822B_MACID_CFG     = 0x40,
+       H2C_8822B_RSSI_REPORT   = 0x42,
+       H2C_8822B_MACID_CFG_3SS = 0x46,
+       /*Not defined CTW CMD for P2P yet*/
+       H2C_8822B_P2P_PS_CTW_CMD        = 0x99,
+       MAX_8822B_H2CCMD
+};
+
+enum rtl8822b_c2h_evt {
+       C2H_8822B_DBG   = 0x00,
+       C2H_8822B_LB    = 0x01,
+       C2H_8822B_TXBF  = 0x02,
+       C2H_8822B_TX_REPORT     = 0x03,
+       C2H_8822B_BT_INFO       = 0x09,
+       C2H_8822B_BT_MP = 0x0B,
+       C2H_8822B_RA_RPT        = 0x0C,
+       MAX_8822B_C2HEVENT
+};
+
+/* H2C: 0x20 */
+#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val)                         \
+       SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 7, __val)
+#define SET_H2CCMD_PWRMODE_PARM_CLK_REQ(__ph2ccmd, __val)                      \
+       SET_BITS_TO_LE_1BYTE(__ph2ccmd, 7, 1, __val)
+#define SET_H2CCMD_PWRMODE_PARM_RLBM(__ph2ccmd, __val)                         \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 4, __val)
+#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val)                     \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 4, 4, __val)
+#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__ph2ccmd, __val)               \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__ph2ccmd, __val)              \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 3, 0, 1, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BCN_EARLY_RPT(__ph2ccmd, __val)                \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 3, 2, 1, __val)
+#define SET_H2CCMD_PWRMODE_PARM_PORT_ID(__ph2ccmd, __val)                      \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 3, 5, 3, __val)
+#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__ph2ccmd, __val)                    \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 4, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BYTE5(__ph2ccmd, __val)                        \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 5, 0, 8, __val)
+
+/* H2C: 0x00 */
+#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val)                    \
+       SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val)                       \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val)                    \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(__ph2ccmd, __val)                \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 3, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(__ph2ccmd, __val)             \
+       SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 4, 0, 8, __val)
+
+/* H2C: 0x01 */
+#define SET_H2CCMD_MSRRPT_PARM_OPMODE(__ph2ccmd, __val)                        \
+       SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 1, __val)
+#define SET_H2CCMD_MSRRPT_PARM_MACID_IND(__ph2ccmd, __val)                     \
+       SET_BITS_TO_LE_1BYTE(__ph2ccmd, 1, 1, __val)
+#define SET_H2CCMD_MSRRPT_PARM_MACID(__ph2ccmd, __val)                         \
+       SET_BITS_TO_LE_1BYTE(__ph2ccmd + 1, 0, 8, __val)
+#define SET_H2CCMD_MSRRPT_PARM_MACID_END(__ph2ccmd, __val)                     \
+       SET_BITS_TO_LE_1BYTE(__ph2ccmd + 2, 0, 8, __val)
+
+/* H2C: 0x2C */
+#define SET_H2CCMD_DFTPID_PORT_ID(__ph2ccmd, __val)                            \
+       SET_BITS_TO_LE_1BYTE(((u8 *)(__ph2ccmd)), 0, 8, (__val))
+#define SET_H2CCMD_DFTPID_MAC_ID(__ph2ccmd, __val)                             \
+       SET_BITS_TO_LE_1BYTE(((u8 *)(__ph2ccmd)) + 1, 0, 8, (__val))
+
+void rtl8822be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, u32 cmd_len,
+                           u8 *cmdbuffer);
+void rtl8822be_set_default_port_id_cmd(struct ieee80211_hw *hw);
+void rtl8822be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl8822be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus);
+void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl8822be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
+void rtl8822be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len);
+void rtl8822be_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
+                                  u8 c2h_cmd_len, u8 *tmp_buf);
+bool rtl8822b_halmac_cb_write_data_rsvd_page(struct rtl_priv *rtlpriv, u8 *buf,
+                                            u32 size);
+bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf,
+                                      u32 size);
+#endif
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../efuse.h"
+#include "../base.h"
+#include "../regd.h"
+#include "../cam.h"
+#include "../ps.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "fw.h"
+#include "led.h"
+#include "hw.h"
+
+#define LLT_CONFIG     5
+
+u8 rtl_channel5g[CHANNEL_MAX_NUMBER_5G] = {
+       36,  38,  40,  42,  44,  46,  48, /* Band 1 */
+       52,  54,  56,  58,  60,  62,  64, /* Band 2 */
+       100, 102, 104, 106, 108, 110, 112, /* Band 3 */
+       116, 118, 120, 122, 124, 126, 128, /* Band 3 */
+       132, 134, 136, 138, 140, 142, 144, /* Band 3 */
+       149, 151, 153, 155, 157, 159, 161, /* Band 4 */
+       165, 167, 169, 171, 173, 175, 177}; /* Band 4 */
+u8 rtl_channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = {42,  58,  106, 122,
+                                                  138, 155, 171};
+
+static void _rtl8822be_set_bcn_ctrl_reg(struct ieee80211_hw *hw, u8 set_bits,
+                                       u8 clear_bits)
+{
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       rtlpci->reg_bcn_ctrl_val |= set_bits;
+       rtlpci->reg_bcn_ctrl_val &= ~clear_bits;
+
+       rtl_write_byte(rtlpriv, REG_BCN_CTRL_8822B,
+                      (u8)rtlpci->reg_bcn_ctrl_val);
+}
+
+static void _rtl8822be_stop_tx_beacon(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 tmp;
+
+       tmp = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL_8822B + 2);
+       rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL_8822B + 2, tmp & (~BIT(6)));
+       rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT_8822B + 1, 0x64);
+       tmp = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT_8822B + 2);
+       tmp &= ~(BIT(0));
+       rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT_8822B + 2, tmp);
+}
+
+static void _rtl8822be_resume_tx_beacon(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 tmp;
+
+       tmp = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL_8822B + 2);
+       rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL_8822B + 2, tmp | BIT(6));
+       rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT_8822B + 1, 0xff);
+       tmp = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT_8822B + 2);
+       tmp |= BIT(0);
+       rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT_8822B + 2, tmp);
+}
+
+static void _rtl8822be_enable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+       _rtl8822be_set_bcn_ctrl_reg(hw, 0, BIT(1));
+}
+
+static void _rtl8822be_disable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+       _rtl8822be_set_bcn_ctrl_reg(hw, BIT(1), 0);
+}
+
+static void _rtl8822be_set_fw_clock_on(struct ieee80211_hw *hw, u8 rpwm_val,
+                                      bool b_need_turn_off_ckk)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       u32 count = 0, isr_regaddr, content;
+       bool b_schedule_timer = b_need_turn_off_ckk;
+
+       if (!rtlhal->fw_ready)
+               return;
+       if (!rtlpriv->psc.fw_current_inpsmode)
+               return;
+
+       while (1) {
+               spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+               if (rtlhal->fw_clk_change_in_progress) {
+                       while (rtlhal->fw_clk_change_in_progress) {
+                               spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+                               count++;
+                               udelay(100);
+                               if (count > 1000)
+                                       return;
+                               spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+                       }
+                       spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+               } else {
+                       rtlhal->fw_clk_change_in_progress = false;
+                       spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+                       break;
+               }
+       }
+
+       if (IS_IN_LOW_POWER_STATE_8822B(rtlhal->fw_ps_state)) {
+               rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM,
+                                             (u8 *)(&rpwm_val));
+               if (FW_PS_IS_ACK(rpwm_val)) {
+                       isr_regaddr = REG_HISR0_8822B;
+                       content = rtl_read_dword(rtlpriv, isr_regaddr);
+                       while (!(content & IMR_CPWM) && (count < 500)) {
+                               udelay(50);
+                               count++;
+                               content = rtl_read_dword(rtlpriv, isr_regaddr);
+                       }
+
+                       if (content & IMR_CPWM) {
+                               rtl_write_word(rtlpriv, isr_regaddr, 0x0100);
+                               rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_8822B;
+                               RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+                                        "Receive CPWM INT!!! PSState = %X\n",
+                                        rtlhal->fw_ps_state);
+                       }
+               }
+
+               spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+               rtlhal->fw_clk_change_in_progress = false;
+               spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+               if (b_schedule_timer) {
+                       mod_timer(&rtlpriv->works.fw_clockoff_timer,
+                                 jiffies + MSECS(10));
+               }
+
+       } else {
+               spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+               rtlhal->fw_clk_change_in_progress = false;
+               spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+       }
+}
+
+static void _rtl8822be_set_fw_clock_off(struct ieee80211_hw *hw, u8 rpwm_val)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl8192_tx_ring *ring;
+       enum rf_pwrstate rtstate;
+       bool b_schedule_timer = false;
+       u8 queue;
+
+       if (!rtlhal->fw_ready)
+               return;
+       if (!rtlpriv->psc.fw_current_inpsmode)
+               return;
+       if (!rtlhal->allow_sw_to_change_hwclc)
+               return;
+
+       rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate));
+       if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF)
+               return;
+
+       for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) {
+               ring = &rtlpci->tx_ring[queue];
+               if (skb_queue_len(&ring->queue)) {
+                       b_schedule_timer = true;
+                       break;
+               }
+       }
+
+       if (b_schedule_timer) {
+               mod_timer(&rtlpriv->works.fw_clockoff_timer,
+                         jiffies + MSECS(10));
+               return;
+       }
+
+       if (FW_PS_STATE(rtlhal->fw_ps_state) != FW_PS_STATE_RF_OFF_LOW_PWR) {
+               spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+               if (!rtlhal->fw_clk_change_in_progress) {
+                       rtlhal->fw_clk_change_in_progress = true;
+                       spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+                       rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val);
+                       rtl_write_word(rtlpriv, REG_HISR0_8822B, 0x0100);
+                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
+                                                     (u8 *)(&rpwm_val));
+                       spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+                       rtlhal->fw_clk_change_in_progress = false;
+                       spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+               } else {
+                       spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+                       mod_timer(&rtlpriv->works.fw_clockoff_timer,
+                                 jiffies + MSECS(10));
+               }
+       }
+}
+
+static void _rtl8822be_set_fw_ps_rf_on(struct ieee80211_hw *hw)
+{
+       u8 rpwm_val = 0;
+
+       rpwm_val |= (FW_PS_STATE_RF_OFF_8822B | FW_PS_ACK);
+       _rtl8822be_set_fw_clock_on(hw, rpwm_val, true);
+}
+
+static void _rtl8822be_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw)
+{
+       u8 rpwm_val = 0;
+
+       rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR;
+       _rtl8822be_set_fw_clock_off(hw, rpwm_val);
+}
+
+void rtl8822be_fw_clk_off_timer_callback(unsigned long data)
+{
+       struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
+
+       _rtl8822be_set_fw_ps_rf_off_low_power(hw);
+}
+
+static void _rtl8822be_fwlps_leave(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       bool fw_current_inps = false;
+       u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE;
+
+       if (ppsc->low_power_enable) {
+               rpwm_val = (FW_PS_STATE_ALL_ON_8822B | FW_PS_ACK); /* RF on */
+               _rtl8822be_set_fw_clock_on(hw, rpwm_val, false);
+               rtlhal->allow_sw_to_change_hwclc = false;
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
+                                             (u8 *)(&fw_pwrmode));
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+                                             (u8 *)(&fw_current_inps));
+       } else {
+               rpwm_val = FW_PS_STATE_ALL_ON_8822B; /* RF on */
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
+                                             (u8 *)(&rpwm_val));
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
+                                             (u8 *)(&fw_pwrmode));
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+                                             (u8 *)(&fw_current_inps));
+       }
+}
+
+static void _rtl8822be_fwlps_enter(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       bool fw_current_inps = true;
+       u8 rpwm_val;
+
+       if (ppsc->low_power_enable) {
+               rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR; /* RF off */
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+                                             (u8 *)(&fw_current_inps));
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
+                                             (u8 *)(&ppsc->fwctrl_psmode));
+               rtlhal->allow_sw_to_change_hwclc = true;
+               _rtl8822be_set_fw_clock_off(hw, rpwm_val);
+       } else {
+               rpwm_val = FW_PS_STATE_RF_OFF_8822B; /* RF off */
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+                                             (u8 *)(&fw_current_inps));
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
+                                             (u8 *)(&ppsc->fwctrl_psmode));
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
+                                             (u8 *)(&rpwm_val));
+       }
+}
+
+void rtl8822be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+       switch (variable) {
+       case HW_VAR_RCR:
+               *((u32 *)(val)) = rtlpci->receive_config;
+               break;
+       case HW_VAR_RF_STATE:
+               *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
+               break;
+       case HW_VAR_FWLPS_RF_ON: {
+               enum rf_pwrstate rf_state;
+               u32 val_rcr;
+
+               rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
+                                             (u8 *)(&rf_state));
+               if (rf_state == ERFOFF) {
+                       *((bool *)(val)) = true;
+               } else {
+                       val_rcr = rtl_read_dword(rtlpriv, REG_RCR_8822B);
+                       val_rcr &= 0x00070000;
+                       if (val_rcr)
+                               *((bool *)(val)) = false;
+                       else
+                               *((bool *)(val)) = true;
+               }
+       } break;
+       case HW_VAR_FW_PSMODE_STATUS:
+               *((bool *)(val)) = ppsc->fw_current_inpsmode;
+               break;
+       case HW_VAR_CORRECT_TSF: {
+               u64 tsf;
+               u32 *ptsf_low = (u32 *)&tsf;
+               u32 *ptsf_high = ((u32 *)&tsf) + 1;
+
+               *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR_8822B + 4));
+               *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR_8822B);
+
+               *((u64 *)(val)) = tsf;
+
+       } break;
+       default:
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+                        "switch case not process %x\n", variable);
+               break;
+       }
+}
+
+static void _rtl8822be_download_rsvd_page(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 tmp_regcr, tmp_reg422;
+       u8 bcnvalid_reg /*, txbc_reg*/;
+       u8 count = 0, dlbcn_count = 0;
+       bool b_recover = false;
+
+       /*Set REG_CR_8822B bit 8. DMA beacon by SW.*/
+       tmp_regcr = rtl_read_byte(rtlpriv, REG_CR_8822B + 1);
+       rtl_write_byte(rtlpriv, REG_CR_8822B + 1, tmp_regcr | BIT(0));
+
+       /* Disable Hw protection for a time which revserd for Hw sending beacon.
+        * Fix download reserved page packet fail
+        * that access collision with the protection time.
+        * 2010.05.11. Added by tynli.
+        */
+       _rtl8822be_set_bcn_ctrl_reg(hw, 0, BIT(3));
+       _rtl8822be_set_bcn_ctrl_reg(hw, BIT(4), 0);
+
+       /* Set FWHW_TXQ_CTRL 0x422[6]=0 to
+        * tell Hw the packet is not a real beacon frame.
+        */
+       tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL_8822B + 2);
+       rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL_8822B + 2,
+                      tmp_reg422 & (~BIT(6)));
+
+       if (tmp_reg422 & BIT(6))
+               b_recover = true;
+
+       do {
+               /* Clear beacon valid check bit */
+               bcnvalid_reg =
+                       rtl_read_byte(rtlpriv, REG_FIFOPAGE_CTRL_2_8822B + 1);
+               bcnvalid_reg = bcnvalid_reg | BIT(7);
+               rtl_write_byte(rtlpriv, REG_FIFOPAGE_CTRL_2_8822B + 1,
+                              bcnvalid_reg);
+
+               /* download rsvd page */
+               rtl8822be_set_fw_rsvdpagepkt(hw, false);
+
+               /* check rsvd page download OK. */
+               bcnvalid_reg =
+                       rtl_read_byte(rtlpriv, REG_FIFOPAGE_CTRL_2_8822B + 1);
+
+               count = 0;
+               while (!(BIT(7) & bcnvalid_reg) && count < 20) {
+                       count++;
+                       udelay(50);
+                       bcnvalid_reg = rtl_read_byte(
+                               rtlpriv, REG_FIFOPAGE_CTRL_2_8822B + 1);
+               }
+
+               dlbcn_count++;
+       } while (!(BIT(7) & bcnvalid_reg) && dlbcn_count < 5);
+
+       if (!(BIT(7) & bcnvalid_reg))
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING,
+                        "Download RSVD page failed!\n");
+
+       /* Enable Bcn */
+       _rtl8822be_set_bcn_ctrl_reg(hw, BIT(3), 0);
+       _rtl8822be_set_bcn_ctrl_reg(hw, 0, BIT(4));
+
+       if (b_recover)
+               rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL_8822B + 2,
+                              tmp_reg422);
+}
+
+void rtl8822be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       struct rtl_efuse *efuse = rtl_efuse(rtl_priv(hw));
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+       switch (variable) {
+       case HW_VAR_ETHER_ADDR:
+               rtlpriv->halmac.ops->halmac_set_mac_address(rtlpriv, 0, val);
+               break;
+       case HW_VAR_BASIC_RATE: {
+               u16 b_rate_cfg = ((u16 *)val)[0];
+
+               b_rate_cfg = b_rate_cfg & 0x15f;
+               b_rate_cfg |= 0x01;
+               b_rate_cfg = (b_rate_cfg | 0xd) & (~BIT(1));
+               rtl_write_byte(rtlpriv, REG_RRSR_8822B, b_rate_cfg & 0xff);
+               rtl_write_byte(rtlpriv, REG_RRSR_8822B + 1,
+                              (b_rate_cfg >> 8) & 0xff);
+       } break;
+       case HW_VAR_BSSID:
+               rtlpriv->halmac.ops->halmac_set_bssid(rtlpriv, 0, val);
+               break;
+       case HW_VAR_SIFS:
+               rtl_write_byte(rtlpriv, REG_SIFS_8822B + 1, val[0]);
+               rtl_write_byte(rtlpriv, REG_SIFS_TRX_8822B + 1, val[1]);
+
+               rtl_write_byte(rtlpriv, REG_SPEC_SIFS_8822B + 1, val[0]);
+               rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS_8822B + 1, val[0]);
+
+               if (!mac->ht_enable)
+                       rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM_8822B,
+                                      0x0e0e);
+               else
+                       rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM_8822B,
+                                      *((u16 *)val));
+               break;
+       case HW_VAR_SLOT_TIME: {
+               u8 e_aci;
+
+               RT_TRACE(rtlpriv, COMP_MLME, DBG_TRACE, "HW_VAR_SLOT_TIME %x\n",
+                        val[0]);
+
+               rtl_write_byte(rtlpriv, REG_SLOT_8822B, val[0]);
+
+               for (e_aci = 0; e_aci < AC_MAX; e_aci++) {
+                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
+                                                     (u8 *)(&e_aci));
+               }
+       } break;
+       case HW_VAR_ACK_PREAMBLE: {
+               u8 reg_tmp;
+               u8 short_preamble = (bool)(*(u8 *)val);
+
+               reg_tmp = (rtlpriv->mac80211.cur_40_prime_sc) << 5;
+               if (short_preamble)
+                       reg_tmp |= 0x80;
+               rtl_write_byte(rtlpriv, REG_RRSR_8822B + 2, reg_tmp);
+               rtlpriv->mac80211.short_preamble = short_preamble;
+       } break;
+       case HW_VAR_WPA_CONFIG:
+               rtl_write_byte(rtlpriv, REG_SECCFG_8822B, *((u8 *)val));
+               break;
+       case HW_VAR_AMPDU_FACTOR: {
+               u32 ampdu_len = (*((u8 *)val));
+
+               ampdu_len = (0x2000 << ampdu_len) - 1;
+               rtl_write_dword(rtlpriv, REG_AMPDU_MAX_LENGTH_8822B, ampdu_len);
+       } break;
+       case HW_VAR_AC_PARAM: {
+               u8 e_aci = *((u8 *)val);
+
+               if (mac->vif && mac->vif->bss_conf.assoc && !mac->act_scanning)
+                       rtl8822be_set_qos(hw, e_aci);
+
+               if (rtlpci->acm_method != EACMWAY2_SW)
+                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL,
+                                                     (u8 *)(&e_aci));
+       } break;
+       case HW_VAR_ACM_CTRL: {
+               u8 e_aci = *((u8 *)val);
+               union aci_aifsn *aifs = (union aci_aifsn *)&mac->ac[0].aifs;
+
+               u8 acm = aifs->f.acm;
+               u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL_8822B);
+
+               acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1);
+
+               if (acm) {
+                       switch (e_aci) {
+                       case AC0_BE:
+                               acm_ctrl |= ACMHW_BEQ_EN;
+                               break;
+                       case AC2_VI:
+                               acm_ctrl |= ACMHW_VIQ_EN;
+                               break;
+                       case AC3_VO:
+                               acm_ctrl |= ACMHW_VOQ_EN;
+                               break;
+                       default:
+                               RT_TRACE(
+                                       rtlpriv, COMP_ERR, DBG_WARNING,
+                                       "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n",
+                                       acm);
+                               break;
+                       }
+               } else {
+                       switch (e_aci) {
+                       case AC0_BE:
+                               acm_ctrl &= (~ACMHW_BEQ_EN);
+                               break;
+                       case AC2_VI:
+                               acm_ctrl &= (~ACMHW_VIQ_EN);
+                               break;
+                       case AC3_VO:
+                               acm_ctrl &= (~ACMHW_VOQ_EN);
+                               break;
+                       default:
+                               RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+                                        "switch case not process\n");
+                               break;
+                       }
+               }
+
+               RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
+                        "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
+                        acm_ctrl);
+               rtl_write_byte(rtlpriv, REG_ACMHWCTRL_8822B, acm_ctrl);
+       } break;
+       case HW_VAR_RCR: {
+               rtl_write_dword(rtlpriv, REG_RCR_8822B, ((u32 *)(val))[0]);
+               rtlpci->receive_config = ((u32 *)(val))[0];
+       } break;
+       case HW_VAR_RETRY_LIMIT: {
+               u8 retry_limit = ((u8 *)(val))[0];
+
+               rtl_write_word(rtlpriv, REG_RETRY_LIMIT_8822B,
+                              retry_limit << RETRY_LIMIT_SHORT_SHIFT |
+                                      retry_limit << RETRY_LIMIT_LONG_SHIFT);
+       } break;
+       case HW_VAR_DUAL_TSF_RST:
+               rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST_8822B,
+                              (BIT(0) | BIT(1)));
+               break;
+       case HW_VAR_EFUSE_BYTES:
+               efuse->efuse_usedbytes = *((u16 *)val);
+               break;
+       case HW_VAR_EFUSE_USAGE:
+               efuse->efuse_usedpercentage = *((u8 *)val);
+               break;
+       case HW_VAR_IO_CMD:
+               rtl8822be_phy_set_io_cmd(hw, (*(enum io_type *)val));
+               break;
+       case HW_VAR_SET_RPWM:
+               break;
+       case HW_VAR_H2C_FW_PWRMODE:
+               rtl8822be_set_fw_pwrmode_cmd(hw, (*(u8 *)val));
+               break;
+       case HW_VAR_FW_PSMODE_STATUS:
+               ppsc->fw_current_inpsmode = *((bool *)val);
+               break;
+       case HW_VAR_RESUME_CLK_ON:
+               _rtl8822be_set_fw_ps_rf_on(hw);
+               break;
+       case HW_VAR_FW_LPS_ACTION: {
+               bool b_enter_fwlps = *((bool *)val);
+
+               if (b_enter_fwlps)
+                       _rtl8822be_fwlps_enter(hw);
+               else
+                       _rtl8822be_fwlps_leave(hw);
+       } break;
+       case HW_VAR_H2C_FW_JOINBSSRPT: {
+               u8 mstatus = (*(u8 *)val);
+
+               if (mstatus == RT_MEDIA_CONNECT) {
+                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL);
+                       _rtl8822be_download_rsvd_page(hw);
+               }
+               rtl8822be_set_default_port_id_cmd(hw);
+               rtl8822be_set_fw_media_status_rpt_cmd(hw, mstatus);
+       } break;
+       case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
+               rtl8822be_set_p2p_ps_offload_cmd(hw, (*(u8 *)val));
+               break;
+       case HW_VAR_AID: {
+               u16 u2btmp;
+
+               u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT_8822B);
+               u2btmp &= 0xC000;
+               rtl_write_word(rtlpriv, REG_BCN_PSR_RPT_8822B,
+                              (u2btmp | mac->assoc_id));
+       } break;
+       case HW_VAR_CORRECT_TSF: {
+               u8 btype_ibss = ((u8 *)(val))[0];
+
+               if (btype_ibss)
+                       _rtl8822be_stop_tx_beacon(hw);
+
+               _rtl8822be_set_bcn_ctrl_reg(hw, 0, BIT(3));
+
+               rtl_write_dword(rtlpriv, REG_TSFTR_8822B,
+                               (u32)(mac->tsf & 0xffffffff));
+               rtl_write_dword(rtlpriv, REG_TSFTR_8822B + 4,
+                               (u32)((mac->tsf >> 32) & 0xffffffff));
+
+               _rtl8822be_set_bcn_ctrl_reg(hw, BIT(3), 0);
+
+               if (btype_ibss)
+                       _rtl8822be_resume_tx_beacon(hw);
+       } break;
+       case HW_VAR_KEEP_ALIVE: {
+               u8 array[2];
+
+               array[0] = 0xff;
+               array[1] = *((u8 *)val);
+               rtl8822be_fill_h2c_cmd(hw, H2C_8822B_KEEP_ALIVE_CTRL, 2, array);
+       } break;
+       default:
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+                        "switch case not process %x\n", variable);
+               break;
+       }
+}
+
+static void _rtl8822be_gen_refresh_led_state(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+       struct rtl_led *led0 = &pcipriv->ledctl.sw_led0;
+
+       if (rtlpriv->rtlhal.up_first_time)
+               return;
+
+       if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+               rtl8822be_sw_led_on(hw, led0);
+       else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
+               rtl8822be_sw_led_on(hw, led0);
+       else
+               rtl8822be_sw_led_off(hw, led0);
+}
+
+static bool _rtl8822be_init_trxbd(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       /*struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));*/
+
+       u8 bytetmp;
+       /*u16 wordtmp;*/
+       u32 dwordtmp;
+
+       /* Set TX/RX descriptor physical address -- HI part */
+       if (!rtlpriv->cfg->mod_params->dma64)
+               goto dma64_end;
+
+       rtl_write_dword(rtlpriv, REG_H2CQ_TXBD_DESA_8822B + 4,
+                       ((u64)rtlpci->tx_ring[H2C_QUEUE].buffer_desc_dma) >>
+                               32);
+       rtl_write_dword(rtlpriv, REG_BCNQ_TXBD_DESA_8822B + 4,
+                       ((u64)rtlpci->tx_ring[BEACON_QUEUE].buffer_desc_dma) >>
+                               32);
+       rtl_write_dword(rtlpriv, REG_MGQ_TXBD_DESA_8822B + 4,
+                       (u64)rtlpci->tx_ring[MGNT_QUEUE].buffer_desc_dma >> 32);
+       rtl_write_dword(rtlpriv, REG_VOQ_TXBD_DESA_8822B + 4,
+                       (u64)rtlpci->tx_ring[VO_QUEUE].buffer_desc_dma >> 32);
+       rtl_write_dword(rtlpriv, REG_VIQ_TXBD_DESA_8822B + 4,
+                       (u64)rtlpci->tx_ring[VI_QUEUE].buffer_desc_dma >> 32);
+       rtl_write_dword(rtlpriv, REG_BEQ_TXBD_DESA_8822B + 4,
+                       (u64)rtlpci->tx_ring[BE_QUEUE].buffer_desc_dma >> 32);
+       rtl_write_dword(rtlpriv, REG_BKQ_TXBD_DESA_8822B + 4,
+                       (u64)rtlpci->tx_ring[BK_QUEUE].buffer_desc_dma >> 32);
+       rtl_write_dword(rtlpriv, REG_HI0Q_TXBD_DESA_8822B + 4,
+                       (u64)rtlpci->tx_ring[HIGH_QUEUE].buffer_desc_dma >> 32);
+
+       rtl_write_dword(rtlpriv, REG_RXQ_RXBD_DESA_8822B + 4,
+                       (u64)rtlpci->rx_ring[RX_MPDU_QUEUE].dma >> 32);
+
+dma64_end:
+       /* Set TX/RX descriptor physical address(from OS API). */
+       rtl_write_dword(rtlpriv, REG_H2CQ_TXBD_DESA_8822B,
+                       ((u64)rtlpci->tx_ring[H2C_QUEUE].buffer_desc_dma) &
+                               DMA_BIT_MASK(32));
+       rtl_write_dword(rtlpriv, REG_BCNQ_TXBD_DESA_8822B,
+                       ((u64)rtlpci->tx_ring[BEACON_QUEUE].buffer_desc_dma) &
+                               DMA_BIT_MASK(32));
+       rtl_write_dword(rtlpriv, REG_MGQ_TXBD_DESA_8822B,
+                       (u64)rtlpci->tx_ring[MGNT_QUEUE].buffer_desc_dma &
+                               DMA_BIT_MASK(32));
+       rtl_write_dword(rtlpriv, REG_VOQ_TXBD_DESA_8822B,
+                       (u64)rtlpci->tx_ring[VO_QUEUE].buffer_desc_dma &
+                               DMA_BIT_MASK(32));
+       rtl_write_dword(rtlpriv, REG_VIQ_TXBD_DESA_8822B,
+                       (u64)rtlpci->tx_ring[VI_QUEUE].buffer_desc_dma &
+                               DMA_BIT_MASK(32));
+       rtl_write_dword(rtlpriv, REG_BEQ_TXBD_DESA_8822B,
+                       (u64)rtlpci->tx_ring[BE_QUEUE].buffer_desc_dma &
+                               DMA_BIT_MASK(32));
+       dwordtmp = rtl_read_dword(rtlpriv, REG_BEQ_TXBD_DESA_8822B); /* need? */
+       rtl_write_dword(rtlpriv, REG_BKQ_TXBD_DESA_8822B,
+                       (u64)rtlpci->tx_ring[BK_QUEUE].buffer_desc_dma &
+                               DMA_BIT_MASK(32));
+       rtl_write_dword(rtlpriv, REG_HI0Q_TXBD_DESA_8822B,
+                       (u64)rtlpci->tx_ring[HIGH_QUEUE].buffer_desc_dma &
+                               DMA_BIT_MASK(32));
+
+       rtl_write_dword(rtlpriv, REG_RXQ_RXBD_DESA_8822B,
+                       (u64)rtlpci->rx_ring[RX_MPDU_QUEUE].dma &
+                               DMA_BIT_MASK(32));
+
+       /* Reset R/W point */
+       rtl_write_dword(rtlpriv, REG_BD_RWPTR_CLR_8822B, 0x3fffffff);
+
+       /* Reset the H2CQ R/W point index to 0 */
+       dwordtmp = rtl_read_dword(rtlpriv, REG_H2CQ_CSR_8822B);
+       rtl_write_dword(rtlpriv, REG_H2CQ_CSR_8822B,
+                       (dwordtmp | BIT(8) | BIT(16)));
+
+       bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_8822B + 3);
+       rtl_write_byte(rtlpriv, REG_PCIE_CTRL_8822B + 3, bytetmp | 0xF7);
+
+       rtl_write_dword(rtlpriv, REG_INT_MIG_8822B, 0);
+
+       rtl_write_dword(rtlpriv, REG_MCUTST_I_8822B, 0x0);
+
+       rtl_write_word(rtlpriv, REG_H2CQ_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_MGQ_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_VOQ_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_VIQ_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_BEQ_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_VOQ_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_BKQ_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_HI0Q_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_HI1Q_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_HI2Q_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_HI3Q_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_HI4Q_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_HI5Q_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_HI6Q_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       rtl_write_word(rtlpriv, REG_HI7Q_TXBD_NUM_8822B,
+                      TX_DESC_NUM_8822B |
+                              ((RTL8822BE_SEG_NUM << 12) & 0x3000));
+       /*Rx*/
+       rtl_write_word(rtlpriv, REG_RX_RXBD_NUM_8822B,
+                      RX_DESC_NUM_8822BE |
+                      ((RTL8822BE_SEG_NUM << 13) & 0x6000) | 0x8000);
+
+       rtl_write_dword(rtlpriv, REG_BD_RWPTR_CLR_8822B, 0XFFFFFFFF);
+
+       _rtl8822be_gen_refresh_led_state(hw);
+
+       return true;
+}
+
+static void _rtl8822be_enable_aspm_back_door(struct ieee80211_hw *hw)
+{
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       u8 tmp;
+
+       if (!ppsc->support_backdoor)
+               return;
+
+       pci_read_config_byte(rtlpci->pdev, 0x70f, &tmp);
+       pci_write_config_byte(rtlpci->pdev, 0x70f, tmp | BIT(7));
+
+       pci_read_config_byte(rtlpci->pdev, 0x719, &tmp);
+       pci_write_config_byte(rtlpci->pdev, 0x719, tmp | BIT(3) | BIT(4));
+}
+
+void rtl8822be_enable_hw_security_config(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 sec_reg_value;
+       u8 tmp;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+                "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
+                rtlpriv->sec.pairwise_enc_algorithm,
+                rtlpriv->sec.group_enc_algorithm);
+
+       if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
+               RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+                        "not open hw encryption\n");
+               return;
+       }
+
+       sec_reg_value = SCR_TX_ENC_ENABLE | SRC_RX_DEC_ENABLE;
+
+       if (rtlpriv->sec.use_defaultkey) {
+               sec_reg_value |= SCR_TX_USE_DK;
+               sec_reg_value |= SCR_RX_USE_DK;
+       }
+
+       sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
+
+       tmp = rtl_read_byte(rtlpriv, REG_CR_8822B + 1);
+       rtl_write_byte(rtlpriv, REG_CR_8822B + 1, tmp | BIT(1));
+
+       RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "The SECR-value %x\n",
+                sec_reg_value);
+
+       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
+}
+
+static bool _rtl8822be_check_pcie_dma_hang(struct rtl_priv *rtlpriv)
+{
+       u8 tmp;
+
+       /* write reg 0x350 Bit[26]=1. Enable debug port. */
+       tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG_V1_8822B + 3);
+       if (!(tmp & BIT(2))) {
+               rtl_write_byte(rtlpriv, REG_DBI_FLAG_V1_8822B + 3,
+                              (tmp | BIT(2)));
+               mdelay(100); /* Suggested by DD Justin_tsai. */
+       }
+
+       /* read reg 0x350 Bit[25] if 1 : RX hang
+        * read reg 0x350 Bit[24] if 1 : TX hang
+        */
+       tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG_V1_8822B + 3);
+       if ((tmp & BIT(0)) || (tmp & BIT(1))) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                        "CheckPcieDMAHang8822BE(): true!!\n");
+               return true;
+       } else {
+               return false;
+       }
+}
+
+static void _rtl8822be_reset_pcie_interface_dma(struct rtl_priv *rtlpriv,
+                                               bool mac_power_on)
+{
+       u8 tmp;
+       bool release_mac_rx_pause;
+       u8 backup_pcie_dma_pause;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                "ResetPcieInterfaceDMA8822BE()\n");
+
+       /* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03"
+        * released by SD1 Alan.
+        * 2013.05.07, by tynli.
+        */
+
+       /* 1. disable register write lock
+        *      write 0x1C bit[1:0] = 2'h0
+        *      write 0xCC bit[2] = 1'b1
+        */
+       tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL_8822B);
+       tmp &= ~(BIT(1) | BIT(0));
+       rtl_write_byte(rtlpriv, REG_RSV_CTRL_8822B, tmp);
+       tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2_8822B);
+       tmp |= BIT(2);
+       rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2_8822B, tmp);
+
+       /* 2. Check and pause TRX DMA
+        *      write 0x284 bit[18] = 1'b1
+        *      write 0x301 = 0xFF
+        */
+       tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL_8822B);
+       if (tmp & BIT(2)) {
+               /* Already pause before the function for another purpose. */
+               release_mac_rx_pause = false;
+       } else {
+               rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL_8822B,
+                              (tmp | BIT(2)));
+               release_mac_rx_pause = true;
+       }
+
+       backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_8822B + 1);
+       if (backup_pcie_dma_pause != 0xFF)
+               rtl_write_byte(rtlpriv, REG_PCIE_CTRL_8822B + 1, 0xFF);
+
+       if (mac_power_on) {
+               /* 3. reset TRX function
+                *      write 0x100 = 0x00
+                */
+               rtl_write_byte(rtlpriv, REG_CR_8822B, 0);
+       }
+
+       /* 4. Reset PCIe DMA
+        *      write 0x003 bit[0] = 0
+        */
+       tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN_8822B + 1);
+       tmp &= ~(BIT(0));
+       rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN_8822B + 1, tmp);
+
+       /* 5. Enable PCIe DMA
+        *      write 0x003 bit[0] = 1
+        */
+       tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN_8822B + 1);
+       tmp |= BIT(0);
+       rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN_8822B + 1, tmp);
+
+       if (mac_power_on) {
+               /* 6. enable TRX function
+                *      write 0x100 = 0xFF
+                */
+               rtl_write_byte(rtlpriv, REG_CR_8822B, 0xFF);
+
+               /* We should init LLT & RQPN and
+                * prepare Tx/Rx descrptor address later
+                * because MAC function is reset.
+                */
+       }
+
+       /* 7. Restore PCIe autoload down bit
+        *      write 0xF8 bit[17] = 1'b1
+        */
+       tmp = rtl_read_byte(rtlpriv, REG_SYS_STATUS2_8822B + 2);
+       tmp |= BIT(1);
+       rtl_write_byte(rtlpriv, REG_SYS_STATUS2_8822B + 2, tmp);
+
+       /* In MAC power on state, BB and RF maybe in ON state,
+        * if we release TRx DMA here
+        * it will cause packets to be started to Tx/Rx,
+        * so we release Tx/Rx DMA later.
+        */
+       if (!mac_power_on) {
+               /* 8. release TRX DMA
+                *      write 0x284 bit[18] = 1'b0
+                *      write 0x301 = 0x00
+                */
+               if (release_mac_rx_pause) {
+                       tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL_8822B);
+                       rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL_8822B,
+                                      (tmp & (~BIT(2))));
+               }
+               rtl_write_byte(rtlpriv, REG_PCIE_CTRL_8822B + 1,
+                              backup_pcie_dma_pause);
+       }
+
+       /* 9. lock system register
+        *      write 0xCC bit[2] = 1'b0
+        */
+       tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2_8822B);
+       tmp &= ~(BIT(2));
+       rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2_8822B, tmp);
+}
+
+int rtl8822be_hw_init(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+       int err = 0;
+       u8 tmp_u1b;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, " Rtl8822BE hw init\n");
+       rtlpriv->rtlhal.being_init_adapter = true;
+       rtlpriv->intf_ops->disable_aspm(hw);
+
+       if (_rtl8822be_check_pcie_dma_hang(rtlpriv)) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "8822be dma hang!\n");
+               _rtl8822be_reset_pcie_interface_dma(rtlpriv,
+                                                   rtlhal->mac_func_enable);
+               rtlhal->mac_func_enable = false;
+       }
+
+       /* init TRX BD */
+       _rtl8822be_init_trxbd(hw);
+
+       /* use halmac to init */
+       err = rtlpriv->halmac.ops->halmac_init_hal(rtlpriv);
+       if (err) {
+               pr_err("halmac_init_hal failed\n");
+               rtlhal->fw_ready = false;
+               return err;
+       }
+
+       rtlhal->fw_ready = true;
+
+       /* have to init after halmac init */
+       tmp_u1b = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_8822B + 2);
+       rtl_write_byte(rtlpriv, REG_PCIE_CTRL_8822B + 2, (tmp_u1b | BIT(4)));
+
+       /*rtl_write_word(rtlpriv, REG_PCIE_CTRL_8822B, 0x8000);*/
+       rtlhal->rx_tag = 0;
+
+       rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ_8822B, 0x4);
+
+       /*fw related variable initialize */
+       ppsc->fw_current_inpsmode = false;
+       rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_8822B;
+       rtlhal->fw_clk_change_in_progress = false;
+       rtlhal->allow_sw_to_change_hwclc = false;
+       rtlhal->last_hmeboxnum = 0;
+
+       rtlphy->rfreg_chnlval[0] =
+               rtl_get_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK);
+       rtlphy->rfreg_chnlval[1] =
+               rtl_get_rfreg(hw, RF90_PATH_B, RF_CHNLBW, RFREG_OFFSET_MASK);
+       rtlphy->backup_rf_0x1a = (u32)rtl_get_rfreg(hw, RF90_PATH_A, RF_RX_G1,
+                                                   RFREG_OFFSET_MASK);
+       rtlphy->rfreg_chnlval[0] =
+               (rtlphy->rfreg_chnlval[0] & 0xfffff3ff) | BIT(10) | BIT(11);
+
+       rtlhal->mac_func_enable = true;
+
+       if (rtlpriv->cfg->ops->get_btc_status())
+               rtlpriv->btcoexist.btc_ops->btc_power_on_setting(rtlpriv);
+
+       /* reset cam / set security */
+       rtl_cam_reset_all_entry(hw);
+       rtl8822be_enable_hw_security_config(hw);
+
+       /* check RCR/ICV bit */
+       rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+       rtl_write_dword(rtlpriv, REG_RCR_8822B, rtlpci->receive_config);
+
+       /* clear rx ctrl frame */
+       rtl_write_word(rtlpriv, REG_RXFLTMAP1_8822B, 0);
+
+       ppsc->rfpwr_state = ERFON;
+
+       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
+       _rtl8822be_enable_aspm_back_door(hw);
+       rtlpriv->intf_ops->enable_aspm(hw);
+
+       if (rtlpriv->cfg->ops->get_btc_status())
+               rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv);
+       else
+               rtlpriv->btcoexist.btc_ops->btc_init_hw_config_wifi_only(
+                                                               rtlpriv);
+
+       rtlpriv->rtlhal.being_init_adapter = false;
+
+       rtlpriv->phydm.ops->phydm_init_dm(rtlpriv);
+
+       /* clear ISR, and IMR will be on later */
+       rtl_write_dword(rtlpriv, REG_HISR0_8822B,
+                       rtl_read_dword(rtlpriv, REG_HISR0_8822B));
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "end of Rtl8822BE hw init %x\n",
+                err);
+       return 0;
+}
+
+static u32 _rtl8822be_read_chip_version(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       /*enum version_8822b version = VERSION_UNKNOWN;*/
+       u32 version;
+       u32 value32;
+
+       rtlphy->rf_type = RF_2T2R;
+
+       value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG1_8822B);
+
+       version = value32;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Chip RF Type: %s\n",
+                (rtlphy->rf_type == RF_2T2R) ? "RF_2T2R" : "RF_1T1R");
+
+       return version;
+}
+
+static int _rtl8822be_set_media_status(struct ieee80211_hw *hw,
+                                      enum nl80211_iftype type)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
+       enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
+       u8 mode = MSR_NOLINK;
+
+       bt_msr &= 0xfc;
+
+       switch (type) {
+       case NL80211_IFTYPE_UNSPECIFIED:
+               mode = MSR_NOLINK;
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+                        "Set Network type to NO LINK!\n");
+               break;
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_MESH_POINT:
+               mode = MSR_ADHOC;
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+                        "Set Network type to Ad Hoc!\n");
+               break;
+       case NL80211_IFTYPE_STATION:
+               mode = MSR_INFRA;
+               ledaction = LED_CTL_LINK;
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+                        "Set Network type to STA!\n");
+               break;
+       case NL80211_IFTYPE_AP:
+               mode = MSR_AP;
+               ledaction = LED_CTL_LINK;
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+                        "Set Network type to AP!\n");
+               break;
+       default:
+               pr_err("Network type %d not support!\n", type);
+               return 1;
+       }
+
+       /* MSR_INFRA == Link in infrastructure network;
+        * MSR_ADHOC == Link in ad hoc network;
+        * Therefore, check link state is necessary.
+        *
+        * MSR_AP == AP mode; link state is not cared here.
+        */
+       if (mode != MSR_AP && rtlpriv->mac80211.link_state < MAC80211_LINKED) {
+               mode = MSR_NOLINK;
+               ledaction = LED_CTL_NO_LINK;
+       }
+
+       if (mode == MSR_NOLINK || mode == MSR_INFRA) {
+               _rtl8822be_stop_tx_beacon(hw);
+               _rtl8822be_enable_bcn_sub_func(hw);
+       } else if (mode == MSR_ADHOC || mode == MSR_AP) {
+               _rtl8822be_resume_tx_beacon(hw);
+               _rtl8822be_disable_bcn_sub_func(hw);
+       } else {
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+                        "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n",
+                        mode);
+       }
+
+       rtl_write_byte(rtlpriv, (MSR), bt_msr | mode);
+       rtlpriv->cfg->ops->led_control(hw, ledaction);
+       if (mode == MSR_AP)
+               rtl_write_byte(rtlpriv, REG_BCNTCFG_8822B + 1, 0x00);
+       else
+               rtl_write_byte(rtlpriv, REG_BCNTCFG_8822B + 1, 0x66);
+       return 0;
+}
+
+void rtl8822be_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       u32 reg_rcr = rtlpci->receive_config;
+
+       if (rtlpriv->psc.rfpwr_state != ERFON)
+               return;
+
+       if (check_bssid) {
+               reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr));
+               _rtl8822be_set_bcn_ctrl_reg(hw, 0, BIT(4));
+       } else if (!check_bssid) {
+               reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+               _rtl8822be_set_bcn_ctrl_reg(hw, BIT(4), 0);
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr));
+       }
+}
+
+int rtl8822be_set_network_type(struct ieee80211_hw *hw,
+                              enum nl80211_iftype type)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       if (_rtl8822be_set_media_status(hw, type))
+               return -EOPNOTSUPP;
+
+       if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+               if (type != NL80211_IFTYPE_AP &&
+                   type != NL80211_IFTYPE_MESH_POINT)
+                       rtl8822be_set_check_bssid(hw, true);
+       } else {
+               rtl8822be_set_check_bssid(hw, false);
+       }
+
+       return 0;
+}
+
+void rtl8822be_set_qos(struct ieee80211_hw *hw, int aci)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_mac *mac = rtl_mac(rtlpriv);
+       u32 ac_param;
+
+       ac_param = rtl_get_hal_edca_param(hw, mac->vif, mac->mode,
+                                         &mac->edca_param[aci]);
+
+       switch (aci) {
+       case AC1_BK:
+               rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM_8822B, ac_param);
+               break;
+       case AC0_BE:
+               rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM_8822B, ac_param);
+               break;
+       case AC2_VI:
+               rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM_8822B, ac_param);
+               break;
+       case AC3_VO:
+               rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM_8822B, ac_param);
+               break;
+       default:
+               WARN_ONCE(true, "invalid aci: %d !\n", aci);
+               break;
+       }
+}
+
+void rtl8822be_enable_interrupt(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+       rtl_write_dword(rtlpriv, REG_HIMR0_8822B,
+                       rtlpci->irq_mask[0] & 0xFFFFFFFF);
+       rtl_write_dword(rtlpriv, REG_HIMR1_8822B,
+                       rtlpci->irq_mask[1] & 0xFFFFFFFF);
+       rtl_write_dword(rtlpriv, REG_HIMR3_8822B,
+                       rtlpci->irq_mask[3] & 0xFFFFFFFF);
+       rtlpci->irq_enabled = true;
+}
+
+void rtl8822be_disable_interrupt(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+       rtl_write_dword(rtlpriv, REG_HIMR0_8822B, IMR_DISABLED);
+       rtl_write_dword(rtlpriv, REG_HIMR1_8822B, IMR_DISABLED);
+       rtl_write_dword(rtlpriv, REG_HIMR3_8822B, IMR_DISABLED);
+       rtlpci->irq_enabled = false;
+       /*synchronize_irq(rtlpci->pdev->irq);*/
+}
+
+void rtl8822be_card_disable(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       enum nl80211_iftype opmode;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8822be card disable\n");
+
+       RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+
+       mac->link_state = MAC80211_NOLINK;
+       opmode = NL80211_IFTYPE_UNSPECIFIED;
+
+       _rtl8822be_set_media_status(hw, opmode);
+
+       if (rtlpriv->rtlhal.driver_is_goingto_unload ||
+           ppsc->rfoff_reason > RF_CHANGE_BY_PS)
+               rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
+
+       rtlpriv->phydm.ops->phydm_deinit_dm(rtlpriv);
+
+       rtlpriv->halmac.ops->halmac_deinit_hal(rtlpriv);
+
+       /* after power off we should do iqk again */
+       if (!rtlpriv->cfg->ops->get_btc_status())
+               rtlpriv->phy.iqk_initialized = false;
+}
+
+void rtl8822be_interrupt_recognized(struct ieee80211_hw *hw, u32 *p_inta,
+                                   u32 *p_intb, u32 *p_intc, u32 *p_intd)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+       *p_inta =
+               rtl_read_dword(rtlpriv, REG_HISR0_8822B) & rtlpci->irq_mask[0];
+       rtl_write_dword(rtlpriv, REG_HISR0_8822B, *p_inta);
+
+       *p_intb =
+               rtl_read_dword(rtlpriv, REG_HISR1_8822B) & rtlpci->irq_mask[1];
+       rtl_write_dword(rtlpriv, REG_HISR1_8822B, *p_intb);
+
+       *p_intd =
+               rtl_read_dword(rtlpriv, REG_HISR3_8822B) & rtlpci->irq_mask[3];
+       rtl_write_dword(rtlpriv, REG_HISR3_8822B, *p_intd);
+}
+
+void rtl8822be_set_beacon_related_registers(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       u16 bcn_interval, atim_window;
+
+       bcn_interval = mac->beacon_interval;
+       atim_window = 2; /*FIX MERGE */
+       rtl8822be_disable_interrupt(hw);
+       rtl_write_word(rtlpriv, REG_ATIMWND_8822B, atim_window);
+       rtl_write_word(rtlpriv, REG_MBSSID_BCN_SPACE_8822B, bcn_interval);
+       rtl_write_word(rtlpriv, REG_BCNTCFG_8822B, 0x660f);
+       rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK_8822B, 0x18);
+       rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM_8822B, 0x18);
+       rtl_write_byte(rtlpriv, 0x606, 0x30);
+       rtlpci->reg_bcn_ctrl_val |= BIT(3);
+       rtl_write_byte(rtlpriv, REG_BCN_CTRL_8822B,
+                      (u8)rtlpci->reg_bcn_ctrl_val);
+}
+
+void rtl8822be_set_beacon_interval(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       u16 bcn_interval = mac->beacon_interval;
+
+       RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, "beacon_interval:%d\n",
+                bcn_interval);
+       rtl_write_word(rtlpriv, REG_MBSSID_BCN_SPACE_8822B, bcn_interval);
+}
+
+void rtl8822be_update_interrupt_mask(struct ieee80211_hw *hw, u32 add_msr,
+                                    u32 rm_msr)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+       RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n",
+                add_msr, rm_msr);
+
+       if (add_msr)
+               rtlpci->irq_mask[0] |= add_msr;
+       if (rm_msr)
+               rtlpci->irq_mask[0] &= (~rm_msr);
+       rtl8822be_disable_interrupt(hw);
+       rtl8822be_enable_interrupt(hw);
+}
+
+static bool _rtl8822be_get_chnl_group(u8 chnl, u8 *group)
+{
+       bool in_24g;
+
+       if (chnl <= 14) {
+               in_24g = true;
+
+               if (chnl >= 1 && chnl <= 2)
+                       *group = 0;
+               else if (chnl >= 3 && chnl <= 5)
+                       *group = 1;
+               else if (chnl >= 6 && chnl <= 8)
+                       *group = 2;
+               else if (chnl >= 9 && chnl <= 11)
+                       *group = 3;
+               else if (chnl >= 12 && chnl <= 14)
+                       *group = 4;
+       } else {
+               in_24g = false;
+
+               if (chnl >= 36 && chnl <= 42)
+                       *group = 0;
+               else if (chnl >= 44 && chnl <= 48)
+                       *group = 1;
+               else if (chnl >= 50 && chnl <= 58)
+                       *group = 2;
+               else if (chnl >= 60 && chnl <= 64)
+                       *group = 3;
+               else if (chnl >= 100 && chnl <= 106)
+                       *group = 4;
+               else if (chnl >= 108 && chnl <= 114)
+                       *group = 5;
+               else if (chnl >= 116 && chnl <= 122)
+                       *group = 6;
+               else if (chnl >= 124 && chnl <= 130)
+                       *group = 7;
+               else if (chnl >= 132 && chnl <= 138)
+                       *group = 8;
+               else if (chnl >= 140 && chnl <= 144)
+                       *group = 9;
+               else if (chnl >= 149 && chnl <= 155)
+                       *group = 10;
+               else if (chnl >= 157 && chnl <= 161)
+                       *group = 11;
+               else if (chnl >= 165 && chnl <= 171)
+                       *group = 12;
+               else if (chnl >= 173 && chnl <= 177)
+                       *group = 13;
+       }
+       return in_24g;
+}
+
+static inline bool power_valid(u8 power)
+{
+       if (power <= 63)
+               return true;
+
+       return false;
+}
+
+static inline s8 power_diff(s8 diff)
+{
+       /* bit sign number to 8 bit sign number */
+       if (diff & BIT(3))
+               diff |= 0xF0;
+
+       return diff;
+}
+
+static void _rtl8822be_read_power_value_fromprom(struct ieee80211_hw *hw,
+                                                struct txpower_info_2g *pwr2g,
+                                                struct txpower_info_5g *pwr5g,
+                                                bool autoload_fail, u8 *hwinfo)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u32 rf, addr = EEPROM_TX_PWR_INX_8822B, group, i = 0;
+       u8 power;
+       s8 diff;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                "hal_ReadPowerValueFromPROM8822B(): PROMContent[0x%x]=0x%x\n",
+                (addr + 1), hwinfo[addr + 1]);
+       if (hwinfo[addr + 1] == 0xFF) /*YJ,add,120316*/
+               autoload_fail = true;
+
+       memset(pwr2g, 0, sizeof(struct txpower_info_2g));
+       memset(pwr5g, 0, sizeof(struct txpower_info_5g));
+
+       if (autoload_fail) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                        "auto load fail : Use Default value!\n");
+               for (rf = 0; rf < MAX_RF_PATH; rf++) {
+                       /* 2.4G default value */
+                       for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
+                               pwr2g->index_cck_base[rf][group] = 0x2D;
+                               pwr2g->index_bw40_base[rf][group] = 0x2D;
+                       }
+                       for (i = 0; i < MAX_TX_COUNT; i++) {
+                               if (i == 0) {
+                                       pwr2g->bw20_diff[rf][0] = 0x02;
+                                       pwr2g->ofdm_diff[rf][0] = 0x04;
+                               } else {
+                                       pwr2g->bw20_diff[rf][i] = 0xFE;
+                                       pwr2g->bw40_diff[rf][i] = 0xFE;
+                                       pwr2g->cck_diff[rf][i] = 0xFE;
+                                       pwr2g->ofdm_diff[rf][i] = 0xFE;
+                               }
+                       }
+
+                       /*5G default value*/
+                       for (group = 0; group < MAX_CHNL_GROUP_5G; group++)
+                               pwr5g->index_bw40_base[rf][group] = 0x2A;
+
+                       for (i = 0; i < MAX_TX_COUNT; i++) {
+                               if (i == 0) {
+                                       pwr5g->ofdm_diff[rf][0] = 0x04;
+                                       pwr5g->bw20_diff[rf][0] = 0x00;
+                                       pwr5g->bw80_diff[rf][0] = 0xFE;
+                                       pwr5g->bw160_diff[rf][0] = 0xFE;
+                               } else {
+                                       pwr5g->ofdm_diff[rf][i] = 0xFE;
+                                       pwr5g->bw20_diff[rf][i] = 0xFE;
+                                       pwr5g->bw40_diff[rf][i] = 0xFE;
+                                       pwr5g->bw80_diff[rf][i] = 0xFE;
+                                       pwr5g->bw160_diff[rf][i] = 0xFE;
+                               }
+                       }
+               }
+               return;
+       }
+
+       rtl_priv(hw)->efuse.txpwr_fromeprom = true;
+
+       for (rf = 0; rf < 2 /*MAX_RF_PATH*/; rf++) {
+               /*2.4G default value*/
+               for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
+                       power = hwinfo[addr++];
+                       if (power_valid(power))
+                               pwr2g->index_cck_base[rf][group] = power;
+               }
+               for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) {
+                       power = hwinfo[addr++];
+                       if (power_valid(power))
+                               pwr2g->index_bw40_base[rf][group] = power;
+               }
+               for (i = 0; i < MAX_TX_COUNT; i++) {
+                       if (i == 0) {
+                               pwr2g->bw40_diff[rf][i] = 0;
+
+                               diff = (hwinfo[addr] & 0xF0) >> 4;
+                               pwr2g->bw20_diff[rf][i] = power_diff(diff);
+
+                               diff = hwinfo[addr] & 0x0F;
+                               pwr2g->ofdm_diff[rf][i] = power_diff(diff);
+
+                               pwr2g->cck_diff[rf][i] = 0;
+
+                               addr++;
+                       } else {
+                               diff = (hwinfo[addr] & 0xF0) >> 4;
+                               pwr2g->bw40_diff[rf][i] = power_diff(diff);
+
+                               diff = hwinfo[addr] & 0x0F;
+                               pwr2g->bw20_diff[rf][i] = power_diff(diff);
+
+                               addr++;
+
+                               diff = (hwinfo[addr] & 0xF0) >> 4;
+                               pwr2g->ofdm_diff[rf][i] = power_diff(diff);
+
+                               diff = hwinfo[addr] & 0x0F;
+                               pwr2g->cck_diff[rf][i] = power_diff(diff);
+
+                               addr++;
+                       }
+               }
+
+               /*5G default value*/
+               for (group = 0; group < MAX_CHNL_GROUP_5G; group++) {
+                       power = hwinfo[addr++];
+                       if (power_valid(power))
+                               pwr5g->index_bw40_base[rf][group] = power;
+               }
+
+               for (i = 0; i < MAX_TX_COUNT; i++) {
+                       if (i == 0) {
+                               pwr5g->bw40_diff[rf][i] = 0;
+
+                               diff = (hwinfo[addr] & 0xF0) >> 4;
+                               pwr5g->bw20_diff[rf][i] = power_diff(diff);
+
+                               diff = hwinfo[addr] & 0x0F;
+                               pwr5g->ofdm_diff[rf][i] = power_diff(diff);
+
+                               addr++;
+                       } else {
+                               diff = (hwinfo[addr] & 0xF0) >> 4;
+                               pwr5g->bw40_diff[rf][i] = power_diff(diff);
+
+                               diff = hwinfo[addr] & 0x0F;
+                               pwr5g->bw20_diff[rf][i] = power_diff(diff);
+
+                               addr++;
+                       }
+               }
+
+               diff = (hwinfo[addr] & 0xF0) >> 4;
+               pwr5g->ofdm_diff[rf][1] = power_diff(diff);
+
+               diff = hwinfo[addr] & 0x0F;
+               pwr5g->ofdm_diff[rf][2] = power_diff(diff);
+
+               addr++;
+
+               diff = hwinfo[addr] & 0x0F;
+               pwr5g->ofdm_diff[rf][3] = power_diff(diff);
+
+               addr++;
+
+               for (i = 0; i < MAX_TX_COUNT; i++) {
+                       diff = (hwinfo[addr] & 0xF0) >> 4;
+                       pwr5g->bw80_diff[rf][i] = power_diff(diff);
+
+                       diff = hwinfo[addr] & 0x0F;
+                       pwr5g->bw160_diff[rf][i] = power_diff(diff);
+
+                       addr++;
+               }
+       }
+}
+
+static void _rtl8822be_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
+                                                  bool autoload_fail,
+                                                  u8 *hwinfo)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_efuse *efu = rtl_efuse(rtl_priv(hw));
+       struct txpower_info_2g pwr2g;
+       struct txpower_info_5g pwr5g;
+       u8 channel5g[CHANNEL_MAX_NUMBER_5G] = {
+               36,  38,  40,  42,  44,  46,  48, /* Band 1 */
+               52,  54,  56,  58,  60,  62,  64, /* Band 2 */
+               100, 102, 104, 106, 108, 110, 112, /* Band 3 */
+               116, 118, 120, 122, 124, 126, 128, /* Band 3 */
+               132, 134, 136, 138, 140, 142, 144, /* Band 3 */
+               149, 151, 153, 155, 157, 159, 161, /* Band 4 */
+               165, 167, 169, 171, 173, 175, 177}; /* Band 4 */
+       u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = {42,  58,  106, 122,
+                                                      138, 155, 171};
+       u8 rf, group;
+       u8 i;
+
+       _rtl8822be_read_power_value_fromprom(hw, &pwr2g, &pwr5g, autoload_fail,
+                                            hwinfo);
+
+       for (rf = 0; rf < MAX_RF_PATH; rf++) {
+               for (i = 0; i < CHANNEL_MAX_NUMBER_2G; i++) {
+                       _rtl8822be_get_chnl_group(i + 1, &group);
+
+                       if (i == CHANNEL_MAX_NUMBER_2G - 1) {
+                               efu->txpwrlevel_cck[rf][i] =
+                                       pwr2g.index_cck_base[rf][5];
+                               efu->txpwrlevel_ht40_1s[rf][i] =
+                                       pwr2g.index_bw40_base[rf][group];
+                       } else {
+                               efu->txpwrlevel_cck[rf][i] =
+                                       pwr2g.index_cck_base[rf][group];
+                               efu->txpwrlevel_ht40_1s[rf][i] =
+                                       pwr2g.index_bw40_base[rf][group];
+                       }
+               }
+               for (i = 0; i < CHANNEL_MAX_NUMBER_5G; i++) {
+                       _rtl8822be_get_chnl_group(channel5g[i], &group);
+                       efu->txpwr_5g_bw40base[rf][i] =
+                               pwr5g.index_bw40_base[rf][group];
+               }
+               for (i = 0; i < CHANNEL_MAX_NUMBER_5G_80M; i++) {
+                       u8 upper, lower;
+
+                       _rtl8822be_get_chnl_group(channel5g_80m[i], &group);
+                       upper = pwr5g.index_bw40_base[rf][group];
+                       lower = pwr5g.index_bw40_base[rf][group + 1];
+
+                       efu->txpwr_5g_bw80base[rf][i] = (upper + lower) / 2;
+               }
+               for (i = 0; i < MAX_TX_COUNT; i++) {
+                       efu->txpwr_cckdiff[rf][i] = pwr2g.cck_diff[rf][i];
+                       efu->txpwr_legacyhtdiff[rf][i] = pwr2g.ofdm_diff[rf][i];
+                       efu->txpwr_ht20diff[rf][i] = pwr2g.bw20_diff[rf][i];
+                       efu->txpwr_ht40diff[rf][i] = pwr2g.bw40_diff[rf][i];
+
+                       efu->txpwr_5g_ofdmdiff[rf][i] = pwr5g.ofdm_diff[rf][i];
+                       efu->txpwr_5g_bw20diff[rf][i] = pwr5g.bw20_diff[rf][i];
+                       efu->txpwr_5g_bw40diff[rf][i] = pwr5g.bw40_diff[rf][i];
+                       efu->txpwr_5g_bw80diff[rf][i] = pwr5g.bw80_diff[rf][i];
+               }
+       }
+
+       if (!autoload_fail)
+               efu->eeprom_thermalmeter = hwinfo[EEPROM_THERMAL_METER_8822B];
+       else
+               efu->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
+
+       if (efu->eeprom_thermalmeter == 0xff || autoload_fail) {
+               efu->apk_thermalmeterignore = true;
+               efu->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
+       }
+
+       efu->thermalmeter[0] = efu->eeprom_thermalmeter;
+       RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "thermalmeter = 0x%x\n",
+               efu->eeprom_thermalmeter);
+
+       if (!autoload_fail) {
+               efu->eeprom_regulatory =
+                       hwinfo[EEPROM_RF_BOARD_OPTION_8822B] & 0x07;
+               if (hwinfo[EEPROM_RF_BOARD_OPTION_8822B] == 0xFF)
+                       efu->eeprom_regulatory = 0;
+       } else {
+               efu->eeprom_regulatory = 0;
+       }
+       RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "eeprom_regulatory = 0x%x\n",
+               efu->eeprom_regulatory);
+}
+
+static void _rtl8822be_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo,
+                                   bool autoload_fail)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+       if (!autoload_fail) {
+               rtlhal->pa_type_2g = hwinfo[EEPROM_2G_5G_PA_TYPE_8822B];
+               rtlhal->lna_type_2g =
+                       hwinfo[EEPROM_2G_LNA_TYPE_GAIN_SEL_AB_8822B];
+               if (rtlhal->pa_type_2g == 0xFF)
+                       rtlhal->pa_type_2g = 0;
+               if (rtlhal->lna_type_2g == 0xFF)
+                       rtlhal->lna_type_2g = 0;
+
+               rtlhal->external_pa_2g = (rtlhal->pa_type_2g & BIT(4)) ? 1 : 0;
+               rtlhal->external_lna_2g =
+                       (rtlhal->lna_type_2g & BIT(3)) ? 1 : 0;
+
+               rtlhal->pa_type_5g = hwinfo[EEPROM_2G_5G_PA_TYPE_8822B];
+               rtlhal->lna_type_5g =
+                       hwinfo[EEPROM_5G_LNA_TYPE_GAIN_SEL_AB_8822B];
+               if (rtlhal->pa_type_5g == 0xFF)
+                       rtlhal->pa_type_5g = 0;
+               if (rtlhal->lna_type_5g == 0xFF)
+                       rtlhal->lna_type_5g = 0;
+
+               rtlhal->external_pa_5g = (rtlhal->pa_type_5g & BIT(0)) ? 1 : 0;
+               rtlhal->external_lna_5g =
+                       (rtlhal->lna_type_5g & BIT(3)) ? 1 : 0;
+       } else {
+               rtlhal->external_pa_2g = 0;
+               rtlhal->external_lna_2g = 0;
+               rtlhal->external_pa_5g = 0;
+               rtlhal->external_lna_5g = 0;
+       }
+}
+
+static void _rtl8822be_read_amplifier_type(struct ieee80211_hw *hw, u8 *hwinfo,
+                                          bool autoload_fail)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+       u8 ext_type_pa_2g_a =
+               (hwinfo[EEPROM_2G_LNA_TYPE_GAIN_SEL_AB_8822B] & BIT(2)) >>
+               2; /* 0xBD[2] */
+       u8 ext_type_pa_2g_b =
+               (hwinfo[EEPROM_2G_LNA_TYPE_GAIN_SEL_AB_8822B] & BIT(6)) >>
+               6; /* 0xBD[6] */
+       u8 ext_type_pa_5g_a =
+               (hwinfo[EEPROM_5G_LNA_TYPE_GAIN_SEL_AB_8822B] & BIT(2)) >>
+               2; /* 0xBF[2] */
+       u8 ext_type_pa_5g_b =
+               (hwinfo[EEPROM_5G_LNA_TYPE_GAIN_SEL_AB_8822B] & BIT(6)) >>
+               6; /* 0xBF[6] */
+       u8 ext_type_lna_2g_a = (hwinfo[EEPROM_2G_LNA_TYPE_GAIN_SEL_AB_8822B] &
+                               (BIT(1) | BIT(0))) >>
+                              0; /* 0xBD[1:0] */
+       u8 ext_type_lna_2g_b = (hwinfo[EEPROM_2G_LNA_TYPE_GAIN_SEL_AB_8822B] &
+                               (BIT(5) | BIT(4))) >>
+                              4; /* 0xBD[5:4] */
+       u8 ext_type_lna_5g_a = (hwinfo[EEPROM_5G_LNA_TYPE_GAIN_SEL_AB_8822B] &
+                               (BIT(1) | BIT(0))) >>
+                              0; /* 0xBF[1:0] */
+       u8 ext_type_lna_5g_b = (hwinfo[EEPROM_5G_LNA_TYPE_GAIN_SEL_AB_8822B] &
+                               (BIT(5) | BIT(4))) >>
+                              4; /* 0xBF[5:4] */
+
+       _rtl8822be_read_pa_type(hw, hwinfo, autoload_fail);
+
+       /* [2.4G] Path A and B are both extPA */
+       if ((rtlhal->pa_type_2g & (BIT(5) | BIT(4))) == (BIT(5) | BIT(4)))
+               rtlhal->type_gpa = ext_type_pa_2g_b << 2 | ext_type_pa_2g_a;
+
+       /* [5G] Path A and B are both extPA */
+       if ((rtlhal->pa_type_5g & (BIT(1) | BIT(0))) == (BIT(1) | BIT(0)))
+               rtlhal->type_apa = ext_type_pa_5g_b << 2 | ext_type_pa_5g_a;
+
+       /* [2.4G] Path A and B are both extLNA */
+       if ((rtlhal->lna_type_2g & (BIT(7) | BIT(3))) == (BIT(7) | BIT(3)))
+               rtlhal->type_glna = ext_type_lna_2g_b << 2 | ext_type_lna_2g_a;
+
+       /* [5G] Path A and B are both extLNA */
+       if ((rtlhal->lna_type_5g & (BIT(7) | BIT(3))) == (BIT(7) | BIT(3)))
+               rtlhal->type_alna = ext_type_lna_5g_b << 2 | ext_type_lna_5g_a;
+}
+
+static void _rtl8822be_read_rfe_type(struct ieee80211_hw *hw, u8 *hwinfo,
+                                    bool autoload_fail)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+       if (!autoload_fail)
+               rtlhal->rfe_type = hwinfo[EEPROM_RFE_OPTION_8822B];
+       else
+               rtlhal->rfe_type = 0;
+
+       if (rtlhal->rfe_type == 0xFF)
+               rtlhal->rfe_type = 0;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RFE Type: 0x%2x\n",
+                rtlhal->rfe_type);
+}
+
+static void _rtl8822be_read_adapter_info(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+       struct rtl_halmac_ops *halmac_ops = rtlpriv->halmac.ops;
+       u16 i, usvalue;
+       u8 *hwinfo;
+       u16 eeprom_id;
+       u32 efuse_size;
+       int err;
+
+       if (rtlefuse->epromtype != EEPROM_BOOT_EFUSE) {
+               pr_err("RTL8822B Not boot from efuse!!");
+               return;
+       }
+
+       /* read logical efuse size (normalely, 0x0300) */
+       err = halmac_ops->halmac_get_logical_efuse_size(rtlpriv, &efuse_size);
+
+       if (err || !efuse_size) {
+               pr_err("halmac_get_logical_efuse_size err=%d efuse_size=0x%X",
+                      err, efuse_size);
+               efuse_size = HWSET_MAX_SIZE;
+       }
+
+       if (efuse_size > HWSET_MAX_SIZE) {
+               pr_err("halmac_get_logical_efuse_size efuse_size=0x%X > 0x%X",
+                      efuse_size, HWSET_MAX_SIZE);
+               efuse_size = HWSET_MAX_SIZE;
+       }
+
+       /* read efuse */
+       hwinfo = kzalloc(efuse_size, GFP_KERNEL);
+
+       err = halmac_ops->halmac_read_logical_efuse_map(rtlpriv, hwinfo,
+                                                       efuse_size);
+       if (err) {
+               pr_err("%s: <ERROR> fail to get efuse map!\n", __func__);
+               goto label_end;
+       }
+
+       /* copy to efuse_map (need?) */
+       memcpy(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], hwinfo,
+              EFUSE_MAX_LOGICAL_SIZE);
+       memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], hwinfo,
+              EFUSE_MAX_LOGICAL_SIZE);
+
+       /* parse content */
+       RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP\n", hwinfo,
+                     HWSET_MAX_SIZE);
+
+       eeprom_id = *((u16 *)&hwinfo[0]);
+       if (eeprom_id != RTL8822B_EEPROM_ID) {
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+                        "EEPROM ID(%#x) is invalid!!\n", eeprom_id);
+               rtlefuse->autoload_failflag = true;
+       } else {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
+               rtlefuse->autoload_failflag = false;
+       }
+
+       if (rtlefuse->autoload_failflag)
+               goto label_end;
+
+       /*VID DID SVID SDID*/
+       rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
+       rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID];
+       rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID];
+       rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID];
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROMId = 0x%4x\n", eeprom_id);
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM VID = 0x%4x\n",
+                rtlefuse->eeprom_vid);
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM DID = 0x%4x\n",
+                rtlefuse->eeprom_did);
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM SVID = 0x%4x\n",
+                rtlefuse->eeprom_svid);
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM SMID = 0x%4x\n",
+                rtlefuse->eeprom_smid);
+       /*customer ID*/
+       rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOM_ID_8822B];
+       if (rtlefuse->eeprom_oemid == 0xFF)
+               rtlefuse->eeprom_oemid = 0;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM Customer ID: 0x%2x\n",
+                rtlefuse->eeprom_oemid);
+       /*EEPROM version*/
+       rtlefuse->eeprom_version = *(u8 *)&hwinfo[EEPROM_VERSION_8822B];
+       /*mac address*/
+       for (i = 0; i < 6; i += 2) {
+               usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_8822BE + i];
+               *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue;
+       }
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "dev_addr: %pM\n",
+                rtlefuse->dev_addr);
+
+       /* channel plan */
+       rtlefuse->eeprom_channelplan =
+               *(u8 *)&hwinfo[EEPROM_CHANNEL_PLAN_8822B];
+
+       /* set channel plan from efuse */
+       rtlefuse->channel_plan = rtlefuse->eeprom_channelplan;
+       if (rtlefuse->channel_plan == 0xFF)
+               rtlefuse->channel_plan = 0x7f; /* use 2G + 5G as default */
+
+       /*tx power*/
+       _rtl8822be_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag,
+                                              hwinfo);
+
+       rtl8822be_read_bt_coexist_info_from_hwpg(
+               hw, rtlefuse->autoload_failflag, hwinfo);
+
+       /*amplifier type*/
+       _rtl8822be_read_amplifier_type(hw, hwinfo, rtlefuse->autoload_failflag);
+
+       /*rfe type*/
+       _rtl8822be_read_rfe_type(hw, hwinfo, rtlefuse->autoload_failflag);
+
+       /*board type*/
+       rtlefuse->board_type =
+               (((*(u8 *)&hwinfo[EEPROM_RF_BOARD_OPTION_8822B]) & 0xE0) >> 5);
+       if ((*(u8 *)&hwinfo[EEPROM_RF_BOARD_OPTION_8822B]) == 0xFF)
+               rtlefuse->board_type = 0;
+
+       if (rtlpriv->btcoexist.btc_info.btcoexist == 1)
+               rtlefuse->board_type |= BIT(2); /* ODM_BOARD_BT */
+
+       /* phydm maintain rtlhal->board_type and rtlhal->package_type */
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "board_type = 0x%x\n",
+                rtlefuse->board_type);
+       /*parse xtal*/
+       rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_8822B];
+       if (hwinfo[EEPROM_XTAL_8822B] == 0xFF)
+               rtlefuse->crystalcap = 0; /*0x20;*/
+
+       /*antenna diversity*/
+       rtlefuse->antenna_div_type = 0;
+       rtlefuse->antenna_div_cfg = 0;
+
+label_end:
+       kfree(hwinfo);
+}
+
+static void _rtl8822be_hal_customized_behavior(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+       pcipriv->ledctl.led_opendrain = true;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "RT Customized ID: 0x%02X\n",
+                rtlhal->oem_id);
+}
+
+static void _rtl8822be_read_pa_bias(struct ieee80211_hw *hw,
+                                   struct rtl_phydm_params *params)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_halmac_ops *halmac_ops = rtlpriv->halmac.ops;
+       u32 size;
+       u8 *map = NULL;
+
+       /* fill default values */
+       params->efuse0x3d7 = 0xFF;
+       params->efuse0x3d8 = 0xFF;
+
+       if (halmac_ops->halmac_get_physical_efuse_size(rtlpriv, &size))
+               goto err;
+
+       map = kmalloc(size, GFP_KERNEL);
+       if (!map)
+               goto err;
+
+       if (halmac_ops->halmac_read_physical_efuse_map(rtlpriv, map, size))
+               goto err;
+
+       params->efuse0x3d7 = map[0x3d7];
+       params->efuse0x3d8 = map[0x3d8];
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                "efuse0x3d7 = 0x%2x, efuse0x3d8 = 0x%2x\n",
+                params->efuse0x3d7, params->efuse0x3d8);
+
+err:
+       kfree(map);
+}
+
+void rtl8822be_read_eeprom_info(struct ieee80211_hw *hw,
+                               struct rtl_phydm_params *params)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       u8 tmp_u1b;
+
+       rtlhal->version = _rtl8822be_read_chip_version(hw);
+
+       params->mp_chip = (rtlhal->version & BIT_RTL_ID_8822B) ? 0 : 1;
+       params->fab_ver = BIT_GET_VENDOR_ID_8822B(rtlhal->version) >> 2;
+       params->cut_ver = BIT_GET_CHIP_VER_8822B(rtlhal->version);
+
+       /* fab_ver mapping */
+       if (params->fab_ver == 2)
+               params->fab_ver = 1;
+       else if (params->fab_ver == 1)
+               params->fab_ver = 2;
+
+       /* read PA bias: params->efuse0x3d7/efuse0x3d8 */
+       _rtl8822be_read_pa_bias(hw, params);
+
+       if (get_rf_type(rtlphy) == RF_1T1R)
+               rtlpriv->dm.rfpath_rxenable[0] = true;
+       else
+               rtlpriv->dm.rfpath_rxenable[0] =
+                       rtlpriv->dm.rfpath_rxenable[1] = true;
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n",
+                rtlhal->version);
+       tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_EEPROM_CTRL_8822B);
+       if (tmp_u1b & BIT(4)) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n");
+               rtlefuse->epromtype = EEPROM_93C46;
+       } else {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n");
+               rtlefuse->epromtype = EEPROM_BOOT_EFUSE;
+       }
+       if (tmp_u1b & BIT(5)) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
+               rtlefuse->autoload_failflag = false;
+               _rtl8822be_read_adapter_info(hw);
+       } else {
+               pr_err("Autoload ERR!!\n");
+       }
+       _rtl8822be_hal_customized_behavior(hw);
+
+       rtlphy->rfpath_rx_enable[0] = true;
+       if (rtlphy->rf_type == RF_2T2R)
+               rtlphy->rfpath_rx_enable[1] = true;
+}
+
+void rtl8822be_read_eeprom_info_dummy(struct ieee80211_hw *hw)
+{
+       /*
+        * 8822b use halmac, so
+        * move rtl8822be_read_eeprom_info() to rtl8822be_init_sw_vars()
+        * after halmac_init_adapter().
+        */
+}
+
+static u32 _rtl8822be_rate_to_bitmap_2ssvht(__le16 vht_rate)
+{
+       u8 i, j, tmp_rate;
+       u32 rate_bitmap = 0;
+
+       for (i = j = 0; i < 4; i += 2, j += 10) {
+               tmp_rate = (le16_to_cpu(vht_rate) >> i) & 3;
+
+               switch (tmp_rate) {
+               case 2:
+                       rate_bitmap = rate_bitmap | (0x03ff << j);
+                       break;
+
+               case 1:
+                       rate_bitmap = rate_bitmap | (0x01ff << j);
+                       break;
+
+               case 0:
+                       rate_bitmap = rate_bitmap | (0x00ff << j);
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       return rate_bitmap;
+}
+
+static u8 _rtl8822be_get_vht_en(enum wireless_mode wirelessmode,
+                               u32 ratr_bitmap)
+{
+       u8 ret = 0;
+
+       if (wirelessmode < WIRELESS_MODE_N_24G) {
+               ret = 0;
+       } else if (wirelessmode == WIRELESS_MODE_AC_24G) {
+               if (ratr_bitmap & 0xfff00000) /* Mix , 2SS */
+                       ret = 3;
+               else /* Mix, 1SS */
+                       ret = 2;
+       } else if (wirelessmode == WIRELESS_MODE_AC_5G) {
+               ret = 1;
+       } /* VHT */
+
+       return ret << 4;
+}
+
+static u8 _rtl8822be_get_ra_ldpc(struct ieee80211_hw *hw, u8 mac_id,
+                                struct rtl_sta_info *sta_entry,
+                                enum wireless_mode wirelessmode)
+{
+       u8 b_ldpc = 0;
+       /*not support ldpc, do not open*/
+       return b_ldpc << 2;
+}
+
+static u8 _rtl8822be_get_ra_rftype(struct ieee80211_hw *hw,
+                                  enum wireless_mode wirelessmode,
+                                  u32 ratr_bitmap)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 rf_type = RF_1T1R;
+
+       if (rtlphy->rf_type == RF_1T1R) {
+               rf_type = RF_1T1R;
+       } else if (wirelessmode == WIRELESS_MODE_AC_5G ||
+                  wirelessmode == WIRELESS_MODE_AC_24G ||
+                  wirelessmode == WIRELESS_MODE_AC_ONLY) {
+               if (ratr_bitmap & 0xffc00000)
+                       rf_type = RF_2T2R;
+       } else if (wirelessmode == WIRELESS_MODE_N_5G ||
+                  wirelessmode == WIRELESS_MODE_N_24G) {
+               if (ratr_bitmap & 0xfff00000)
+                       rf_type = RF_2T2R;
+       }
+
+       return rf_type;
+}
+
+static bool _rtl8822be_get_ra_shortgi(struct ieee80211_hw *hw,
+                                     struct ieee80211_sta *sta, u8 mac_id)
+{
+       bool b_short_gi = false;
+       u8 b_curshortgi_40mhz =
+               (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
+       u8 b_curshortgi_20mhz =
+               (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
+       u8 b_curshortgi_80mhz = 0;
+
+       b_curshortgi_80mhz =
+               (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) ? 1 : 0;
+
+       if (mac_id == 99 /*MAC_ID_STATIC_FOR_BROADCAST_MULTICAST*/)
+               b_short_gi = false;
+
+       if (b_curshortgi_40mhz || b_curshortgi_80mhz || b_curshortgi_20mhz)
+               b_short_gi = true;
+
+       return b_short_gi;
+}
+
+static void rtl8822be_update_hal_rate_mask(struct ieee80211_hw *hw,
+                                          struct ieee80211_sta *sta,
+                                          u8 rssi_level, bool update_bw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       struct rtl_sta_info *sta_entry = NULL;
+       u32 ratr_bitmap, ratr_bitmap_msb = 0;
+       u8 ratr_index;
+       enum wireless_mode wirelessmode = 0;
+       u8 curtxbw_40mhz =
+               (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0;
+       bool b_shortgi = false;
+       u8 rate_mask[7];
+       u8 macid = 0;
+       u8 rf_type;
+
+       sta_entry = (struct rtl_sta_info *)sta->drv_priv;
+       wirelessmode = sta_entry->wireless_mode;
+
+       RT_TRACE(rtlpriv, COMP_RATR, DBG_LOUD, "wireless mode = 0x%x\n",
+                wirelessmode);
+       if (mac->opmode == NL80211_IFTYPE_STATION ||
+           mac->opmode == NL80211_IFTYPE_MESH_POINT) {
+               curtxbw_40mhz = mac->bw_40;
+       } else if (mac->opmode == NL80211_IFTYPE_AP ||
+                  mac->opmode == NL80211_IFTYPE_ADHOC)
+               macid = sta->aid + 1;
+       if (wirelessmode == WIRELESS_MODE_N_5G ||
+           wirelessmode == WIRELESS_MODE_AC_5G ||
+           wirelessmode == WIRELESS_MODE_A)
+               ratr_bitmap = (sta->supp_rates[NL80211_BAND_5GHZ]) << 4;
+       else
+               ratr_bitmap = sta->supp_rates[NL80211_BAND_2GHZ];
+
+       if (mac->opmode == NL80211_IFTYPE_ADHOC)
+               ratr_bitmap = 0xfff;
+
+       if (wirelessmode == WIRELESS_MODE_N_24G ||
+           wirelessmode == WIRELESS_MODE_N_5G)
+               ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+                               sta->ht_cap.mcs.rx_mask[0] << 12);
+       else if (wirelessmode == WIRELESS_MODE_AC_24G ||
+                wirelessmode == WIRELESS_MODE_AC_5G ||
+                wirelessmode == WIRELESS_MODE_AC_ONLY)
+               ratr_bitmap |= _rtl8822be_rate_to_bitmap_2ssvht(
+                                      sta->vht_cap.vht_mcs.rx_mcs_map)
+                              << 12;
+
+       b_shortgi = _rtl8822be_get_ra_shortgi(hw, sta, macid);
+       rf_type = _rtl8822be_get_ra_rftype(hw, wirelessmode, ratr_bitmap);
+
+       ratr_index = rtlpriv->phydm.ops->phydm_rate_id_mapping(
+               rtlpriv, wirelessmode, rf_type, rtlphy->current_chan_bw);
+       sta_entry->ratr_index = ratr_index;
+
+       rtlpriv->phydm.ops->phydm_get_ra_bitmap(
+               rtlpriv, wirelessmode, rf_type, rtlphy->current_chan_bw,
+               rssi_level, &ratr_bitmap_msb, &ratr_bitmap);
+
+       RT_TRACE(rtlpriv, COMP_RATR, DBG_LOUD, "ratr_bitmap :%x\n",
+                ratr_bitmap);
+
+       rate_mask[0] = macid;
+       rate_mask[1] = ratr_index | (b_shortgi ? 0x80 : 0x00);
+       rate_mask[2] =
+               rtlphy->current_chan_bw | ((!update_bw) << 3) |
+               _rtl8822be_get_vht_en(wirelessmode, ratr_bitmap) |
+               _rtl8822be_get_ra_ldpc(hw, macid, sta_entry, wirelessmode);
+
+       rate_mask[3] = (u8)(ratr_bitmap & 0x000000ff);
+       rate_mask[4] = (u8)((ratr_bitmap & 0x0000ff00) >> 8);
+       rate_mask[5] = (u8)((ratr_bitmap & 0x00ff0000) >> 16);
+       rate_mask[6] = (u8)((ratr_bitmap & 0xff000000) >> 24);
+
+       RT_TRACE(
+               rtlpriv, COMP_RATR, DBG_DMESG,
+               "Rate_index:%x, ratr_val:%08x, %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+               ratr_index, ratr_bitmap, rate_mask[0], rate_mask[1],
+               rate_mask[2], rate_mask[3], rate_mask[4], rate_mask[5],
+               rate_mask[6]);
+       rtl8822be_fill_h2c_cmd(hw, H2C_8822B_MACID_CFG, 7, rate_mask);
+
+       /* for h2c cmd 0x46, only modify cmd id & ra mask */
+       /* Keep rate_mask0~2 of cmd 0x40, but clear byte3 and later */
+       /* 8822B has no 3SS, so keep it zeros. */
+       memset(rate_mask + 3, 0, 4);
+
+       rtl8822be_fill_h2c_cmd(hw, H2C_8822B_MACID_CFG_3SS, 7, rate_mask);
+
+       _rtl8822be_set_bcn_ctrl_reg(hw, BIT(3), 0);
+}
+
+void rtl8822be_update_hal_rate_tbl(struct ieee80211_hw *hw,
+                                  struct ieee80211_sta *sta, u8 rssi_level,
+                                  bool update_bw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       if (rtlpriv->dm.useramask)
+               rtl8822be_update_hal_rate_mask(hw, sta, rssi_level, update_bw);
+}
+
+void rtl8822be_update_channel_access_setting(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       u16 sifs_timer;
+
+       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
+                                     (u8 *)&mac->slot_time);
+       if (!mac->ht_enable)
+               sifs_timer = 0x0a0a;
+       else
+               sifs_timer = 0x0e0e;
+       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
+}
+
+bool rtl8822be_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
+{
+       *valid = 1;
+       return true;
+}
+
+void rtl8822be_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr,
+                      bool is_group, u8 enc_algo, bool is_wepkey,
+                      bool clear_all)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+       u8 *macaddr = p_macaddr;
+       u32 entry_id = 0;
+       bool is_pairwise = false;
+
+       static u8 cam_const_addr[4][6] = {
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
+       };
+       static u8 cam_const_broad[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+       if (clear_all) {
+               u8 idx = 0;
+               u8 cam_offset = 0;
+               u8 clear_number = 5;
+
+               RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n");
+
+               for (idx = 0; idx < clear_number; idx++) {
+                       rtl_cam_mark_invalid(hw, cam_offset + idx);
+                       rtl_cam_empty_entry(hw, cam_offset + idx);
+
+                       if (idx < 5) {
+                               memset(rtlpriv->sec.key_buf[idx], 0,
+                                      MAX_KEY_LEN);
+                               rtlpriv->sec.key_len[idx] = 0;
+                       }
+               }
+
+               return;
+       }
+
+       switch (enc_algo) {
+       case WEP40_ENCRYPTION:
+               enc_algo = CAM_WEP40;
+               break;
+       case WEP104_ENCRYPTION:
+               enc_algo = CAM_WEP104;
+               break;
+       case TKIP_ENCRYPTION:
+               enc_algo = CAM_TKIP;
+               break;
+       case AESCCMP_ENCRYPTION:
+               enc_algo = CAM_AES;
+               break;
+       default:
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
+                        "switch case %#x not processed\n", enc_algo);
+               enc_algo = CAM_TKIP;
+               break;
+       }
+
+       if (is_wepkey || rtlpriv->sec.use_defaultkey) {
+               macaddr = cam_const_addr[key_index];
+               entry_id = key_index;
+       } else {
+               if (is_group) {
+                       macaddr = cam_const_broad;
+                       entry_id = key_index;
+               } else {
+                       if (mac->opmode == NL80211_IFTYPE_AP) {
+                               entry_id =
+                                       rtl_cam_get_free_entry(hw, p_macaddr);
+                               if (entry_id >= TOTAL_CAM_ENTRY) {
+                                       pr_err("Can not find free hwsecurity cam entry\n");
+                                       return;
+                               }
+                       } else {
+                               entry_id = CAM_PAIRWISE_KEY_POSITION;
+                       }
+
+                       key_index = PAIRWISE_KEYIDX;
+                       is_pairwise = true;
+               }
+       }
+
+       if (rtlpriv->sec.key_len[key_index] == 0) {
+               RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+                        "delete one entry, entry_id is %d\n", entry_id);
+               if (mac->opmode == NL80211_IFTYPE_AP)
+                       rtl_cam_del_entry(hw, p_macaddr);
+               rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
+       } else {
+               RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "add one entry\n");
+               if (is_pairwise) {
+                       RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+                                "set Pairwise key\n");
+
+                       rtl_cam_add_one_entry(hw, macaddr, key_index, entry_id,
+                                             enc_algo, CAM_CONFIG_NO_USEDK,
+                                             rtlpriv->sec.key_buf[key_index]);
+               } else {
+                       RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+                                "set group key\n");
+
+                       if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+                               rtl_cam_add_one_entry(
+                                       hw, rtlefuse->dev_addr, PAIRWISE_KEYIDX,
+                                       CAM_PAIRWISE_KEY_POSITION, enc_algo,
+                                       CAM_CONFIG_NO_USEDK,
+                                       rtlpriv->sec.key_buf[entry_id]);
+                       }
+
+                       rtl_cam_add_one_entry(hw, macaddr, key_index, entry_id,
+                                             enc_algo, CAM_CONFIG_NO_USEDK,
+                                             rtlpriv->sec.key_buf[entry_id]);
+               }
+       }
+}
+
+void rtl8822be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
+                                             bool auto_load_fail, u8 *hwinfo)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 value;
+       u32 val32;
+
+       val32 = rtl_read_dword(rtlpriv, REG_WL_BT_PWR_CTRL_8822B);
+       if (val32 & BIT_BT_FUNC_EN_8822B)
+               rtlpriv->btcoexist.btc_info.btcoexist = 1;
+       else
+               rtlpriv->btcoexist.btc_info.btcoexist = 0;
+
+       if (!auto_load_fail) {
+               value = hwinfo[EEPROM_RF_BT_SETTING_8822B];
+
+               rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8822B;
+               rtlpriv->btcoexist.btc_info.ant_num =
+                       (value & BIT(0) ? ANT_TOTAL_X1 : ANT_TOTAL_X2);
+       } else {
+               rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8822B;
+               rtlpriv->btcoexist.btc_info.ant_num = ANT_TOTAL_X2;
+       }
+}
+
+void rtl8822be_bt_reg_init(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       /* 0:Low, 1:High, 2:From Efuse. */
+       rtlpriv->btcoexist.reg_bt_iso = 2;
+       /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */
+       rtlpriv->btcoexist.reg_bt_sco = 3;
+       /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
+       rtlpriv->btcoexist.reg_bt_sco = 0;
+}
+
+void rtl8822be_suspend(struct ieee80211_hw *hw) {}
+
+void rtl8822be_resume(struct ieee80211_hw *hw) {}
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8822B_HW_H__
+#define __RTL8822B_HW_H__
+
+extern u8 rtl_channel5g[CHANNEL_MAX_NUMBER_5G];
+extern u8 rtl_channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M];
+
+void rtl8822be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl8822be_read_eeprom_info(struct ieee80211_hw *hw,
+                               struct rtl_phydm_params *params);
+void rtl8822be_read_eeprom_info_dummy(struct ieee80211_hw *hw);
+void rtl8822be_interrupt_recognized(struct ieee80211_hw *hw, u32 *p_inta,
+                                   u32 *p_intb, u32 *p_intc, u32 *p_intd);
+int rtl8822be_hw_init(struct ieee80211_hw *hw);
+void rtl8822be_card_disable(struct ieee80211_hw *hw);
+void rtl8822be_enable_interrupt(struct ieee80211_hw *hw);
+void rtl8822be_disable_interrupt(struct ieee80211_hw *hw);
+int rtl8822be_set_network_type(struct ieee80211_hw *hw,
+                              enum nl80211_iftype type);
+void rtl8822be_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
+void rtl8822be_set_qos(struct ieee80211_hw *hw, int aci);
+void rtl8822be_set_beacon_related_registers(struct ieee80211_hw *hw);
+void rtl8822be_set_beacon_interval(struct ieee80211_hw *hw);
+void rtl8822be_update_interrupt_mask(struct ieee80211_hw *hw, u32 add_msr,
+                                    u32 rm_msr);
+void rtl8822be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl8822be_update_hal_rate_tbl(struct ieee80211_hw *hw,
+                                  struct ieee80211_sta *sta, u8 rssi_level,
+                                  bool update_bw);
+void rtl8822be_update_channel_access_setting(struct ieee80211_hw *hw);
+bool rtl8822be_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
+void rtl8822be_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr,
+                      bool is_group, u8 enc_algo, bool is_wepkey,
+                      bool clear_all);
+void rtl8822be_enable_hw_security_config(struct ieee80211_hw *hw);
+void rtl8822be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
+                                             bool autoload_fail, u8 *hwinfo);
+void rtl8822be_bt_reg_init(struct ieee80211_hw *hw);
+void rtl8822be_suspend(struct ieee80211_hw *hw);
+void rtl8822be_resume(struct ieee80211_hw *hw);
+void rtl8822be_fw_clk_off_timer_callback(unsigned long data);
+#endif
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "reg.h"
+#include "led.h"
+
+static void _rtl8822be_init_led(struct ieee80211_hw *hw, struct rtl_led *pled,
+                               enum rtl_led_pin ledpin)
+{
+       pled->hw = hw;
+       pled->ledpin = ledpin;
+       pled->ledon = false;
+}
+
+void rtl8822be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
+                REG_LEDCFG2_8822B, pled->ledpin);
+
+       switch (pled->ledpin) {
+       case LED_PIN_GPIO0:
+               break;
+       case LED_PIN_LED0:
+               break;
+       case LED_PIN_LED1:
+               break;
+       default:
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
+                        "switch case not process\n");
+               break;
+       }
+       pled->ledon = true;
+}
+
+void rtl8822be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
+                REG_LEDCFG2_8822B, pled->ledpin);
+
+       switch (pled->ledpin) {
+       case LED_PIN_GPIO0:
+               break;
+       case LED_PIN_LED0:
+               break;
+       case LED_PIN_LED1:
+
+               break;
+       default:
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
+                        "switch case not process\n");
+               break;
+       }
+       pled->ledon = false;
+}
+
+void rtl8822be_init_sw_leds(struct ieee80211_hw *hw)
+{
+       struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+
+       _rtl8822be_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0);
+       _rtl8822be_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1);
+}
+
+static void _rtl8822be_sw_led_control(struct ieee80211_hw *hw,
+                                     enum led_ctl_mode ledaction)
+{
+       struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+       struct rtl_led *led0 = &pcipriv->ledctl.sw_led0;
+
+       switch (ledaction) {
+       case LED_CTL_POWER_ON:
+       case LED_CTL_LINK:
+       case LED_CTL_NO_LINK:
+               rtl8822be_sw_led_on(hw, led0);
+               break;
+       case LED_CTL_POWER_OFF:
+               rtl8822be_sw_led_off(hw, led0);
+               break;
+       default:
+               break;
+       }
+}
+
+void rtl8822be_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+       if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
+           (ledaction == LED_CTL_TX || ledaction == LED_CTL_RX ||
+            ledaction == LED_CTL_SITE_SURVEY || ledaction == LED_CTL_LINK ||
+            ledaction == LED_CTL_NO_LINK ||
+            ledaction == LED_CTL_START_TO_LINK ||
+            ledaction == LED_CTL_POWER_ON)) {
+               return;
+       }
+       RT_TRACE(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n", ledaction);
+       _rtl8822be_sw_led_control(hw, ledaction);
+}
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8822B_LED_H__
+#define __RTL8822B_LED_H__
+
+void rtl8822be_init_sw_leds(struct ieee80211_hw *hw);
+void rtl8822be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8822be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8822be_led_control(struct ieee80211_hw *hw,
+                          enum led_ctl_mode ledaction);
+#endif
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../ps.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "trx.h"
+#include "../btcoexist/halbt_precomp.h"
+#include "hw.h"
+#include "../efuse.h"
+
+static u32 _rtl8822be_phy_calculate_bit_shift(u32 bitmask);
+static void
+_rtl8822be_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw);
+
+static long _rtl8822be_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
+                                           enum wireless_mode wirelessmode,
+                                           u8 txpwridx);
+static void rtl8822be_phy_set_rf_on(struct ieee80211_hw *hw);
+static void rtl8822be_phy_set_io(struct ieee80211_hw *hw);
+
+static u8 cck_rates[] = {DESC_RATE1M, DESC_RATE2M, DESC_RATE5_5M, DESC_RATE11M};
+static u8 sizes_of_cck_retes = 4;
+static u8 ofdm_rates[] = {DESC_RATE6M,  DESC_RATE9M,  DESC_RATE12M,
+                         DESC_RATE18M, DESC_RATE24M, DESC_RATE36M,
+                         DESC_RATE48M, DESC_RATE54M};
+static u8 sizes_of_ofdm_retes = 8;
+static u8 ht_rates_1t[] = {DESC_RATEMCS0, DESC_RATEMCS1, DESC_RATEMCS2,
+                          DESC_RATEMCS3, DESC_RATEMCS4, DESC_RATEMCS5,
+                          DESC_RATEMCS6, DESC_RATEMCS7};
+static u8 sizes_of_ht_retes_1t = 8;
+static u8 ht_rates_2t[] = {DESC_RATEMCS8,  DESC_RATEMCS9,  DESC_RATEMCS10,
+                          DESC_RATEMCS11, DESC_RATEMCS12, DESC_RATEMCS13,
+                          DESC_RATEMCS14, DESC_RATEMCS15};
+static u8 sizes_of_ht_retes_2t = 8;
+static u8 vht_rates_1t[] = {DESC_RATEVHT1SS_MCS0, DESC_RATEVHT1SS_MCS1,
+                           DESC_RATEVHT1SS_MCS2, DESC_RATEVHT1SS_MCS3,
+                           DESC_RATEVHT1SS_MCS4, DESC_RATEVHT1SS_MCS5,
+                           DESC_RATEVHT1SS_MCS6, DESC_RATEVHT1SS_MCS7,
+                           DESC_RATEVHT1SS_MCS8, DESC_RATEVHT1SS_MCS9};
+static u8 vht_rates_2t[] = {DESC_RATEVHT2SS_MCS0, DESC_RATEVHT2SS_MCS1,
+                           DESC_RATEVHT2SS_MCS2, DESC_RATEVHT2SS_MCS3,
+                           DESC_RATEVHT2SS_MCS4, DESC_RATEVHT2SS_MCS5,
+                           DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7,
+                           DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9};
+static u8 sizes_of_vht_retes = 10;
+
+u32 rtl8822be_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr,
+                              u32 bitmask)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u32 returnvalue, originalvalue, bitshift;
+
+       RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n",
+                regaddr, bitmask);
+       originalvalue = rtl_read_dword(rtlpriv, regaddr);
+       bitshift = _rtl8822be_phy_calculate_bit_shift(bitmask);
+       returnvalue = (originalvalue & bitmask) >> bitshift;
+
+       RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "BBR MASK=0x%x Addr[0x%x]=0x%x\n",
+                bitmask, regaddr, originalvalue);
+
+       return returnvalue;
+}
+
+void rtl8822be_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
+                             u32 data)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u32 originalvalue, bitshift;
+
+       RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+                "regaddr(%#x), bitmask(%#x), data(%#x)\n", regaddr, bitmask,
+                data);
+
+       if (bitmask != MASKDWORD) {
+               originalvalue = rtl_read_dword(rtlpriv, regaddr);
+               bitshift = _rtl8822be_phy_calculate_bit_shift(bitmask);
+               data = ((originalvalue & (~bitmask)) |
+                       ((data << bitshift) & bitmask));
+       }
+
+       rtl_write_dword(rtlpriv, regaddr, data);
+
+       RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+                "regaddr(%#x), bitmask(%#x), data(%#x)\n", regaddr, bitmask,
+                data);
+}
+
+u32 rtl8822be_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+                              u32 regaddr, u32 bitmask)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u32 /*original_value,*/ readback_value /*, bitshift*/;
+       unsigned long flags;
+
+       RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+                "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", regaddr, rfpath,
+                bitmask);
+
+       spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+
+       readback_value = rtlpriv->phydm.ops->phydm_read_rf_reg(
+               rtlpriv, rfpath, regaddr, bitmask);
+
+       spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+
+       return readback_value;
+}
+
+void rtl8822be_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+                             u32 regaddr, u32 bitmask, u32 data)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       unsigned long flags;
+
+       RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+                "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+                regaddr, bitmask, data, rfpath);
+
+       spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+
+       rtlpriv->phydm.ops->phydm_write_rf_reg(rtlpriv, rfpath, regaddr,
+                                              bitmask, data);
+
+       spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+
+       RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+                "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+                regaddr, bitmask, data, rfpath);
+}
+
+static u32 _rtl8822be_phy_calculate_bit_shift(u32 bitmask)
+{
+       u32 i;
+
+       for (i = 0; i <= 31; i++) {
+               if (((bitmask >> i) & 0x1) == 1)
+                       break;
+       }
+       return i;
+}
+
+bool rtl8822be_halmac_cb_init_mac_register(struct rtl_priv *rtlpriv)
+{
+       return rtlpriv->phydm.ops->phydm_phy_mac_config(rtlpriv);
+}
+
+bool rtl8822be_phy_bb_config(struct ieee80211_hw *hw)
+{
+       bool rtstatus = true;
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+       u8 crystal_cap;
+       /* u32 tmp; */
+
+       rtstatus = rtlpriv->phydm.ops->phydm_phy_bb_config(rtlpriv);
+
+       /* write 0x28[6:1] = 0x24[30:25] = CrystalCap */
+       crystal_cap = rtlefuse->crystalcap & 0x3F;
+       rtl_set_bbreg(hw, REG_AFE_XTAL_CTRL_8822B, 0x7E000000, crystal_cap);
+       rtl_set_bbreg(hw, REG_AFE_PLL_CTRL_8822B, 0x7E, crystal_cap);
+
+       /*rtlphy->reg_837 = rtl_read_byte(rtlpriv, 0x837);*/ /*unused*/
+
+       return rtstatus;
+}
+
+bool rtl8822be_phy_rf_config(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+
+       if (rtlphy->rf_type == RF_1T1R)
+               rtlphy->num_total_rfpath = 1;
+       else
+               rtlphy->num_total_rfpath = 2;
+
+       return rtlpriv->phydm.ops->phydm_phy_rf_config(rtlpriv);
+}
+
+bool rtl8822be_halmac_cb_init_bb_rf_register(struct rtl_priv *rtlpriv)
+{
+       struct ieee80211_hw *hw = rtlpriv->hw;
+       enum radio_mask txpath, rxpath;
+       bool tx2path;
+       bool ret = false;
+
+       _rtl8822be_phy_init_bb_rf_register_definition(hw);
+
+       rtlpriv->halmac.ops->halmac_phy_power_switch(rtlpriv, 1);
+
+       /* beofre bb/rf config */
+       rtlpriv->phydm.ops->phydm_parameter_init(rtlpriv, 0);
+
+       /* do bb/rf config */
+       if (rtl8822be_phy_bb_config(hw) && rtl8822be_phy_rf_config(hw))
+               ret = true;
+
+       /* after bb/rf config */
+       rtlpriv->phydm.ops->phydm_parameter_init(rtlpriv, 1);
+
+       /* set trx mode (keep it to be last, r17376) */
+       txpath = RF_MASK_A | RF_MASK_B;
+       rxpath = RF_MASK_A | RF_MASK_B;
+       tx2path = false;
+       ret = rtlpriv->phydm.ops->phydm_trx_mode(rtlpriv, txpath, rxpath,
+                                                tx2path);
+
+       return ret;
+}
+
+static void _rtl8822be_phy_init_tx_power_by_rate(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+
+       u8 band, rfpath, txnum, rate;
+
+       for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band)
+               for (rfpath = 0; rfpath < TX_PWR_BY_RATE_NUM_RF; ++rfpath)
+                       for (txnum = 0; txnum < TX_PWR_BY_RATE_NUM_RF; ++txnum)
+                               for (rate = 0; rate < TX_PWR_BY_RATE_NUM_RATE;
+                                    ++rate)
+                                       rtlphy->tx_power_by_rate_offset
+                                               [band][rfpath][txnum][rate] = 0;
+}
+
+static void _rtl8822be_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw,
+                                                   u8 band, u8 path,
+                                                   u8 rate_section, u8 txnum,
+                                                   u8 value)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+
+       if (path > RF90_PATH_D) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                        "Invalid Rf Path %d in phy_SetTxPowerByRatBase()\n",
+                        path);
+               return;
+       }
+
+       if (band != BAND_ON_2_4G && band != BAND_ON_5G) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                        "Invalid band %d in phy_SetTxPowerByRatBase()\n",
+                        band);
+               return;
+       }
+
+       if (rate_section >= MAX_RATE_SECTION ||
+           (band == BAND_ON_5G && rate_section == CCK)) {
+               RT_TRACE(
+                       rtlpriv, COMP_INIT, DBG_LOUD,
+                       "Invalid rate_section %d in phy_SetTxPowerByRatBase()\n",
+                       rate_section);
+               return;
+       }
+
+       if (band == BAND_ON_2_4G)
+               rtlphy->txpwr_by_rate_base_24g[path][txnum][rate_section] =
+                       value;
+       else /* BAND_ON_5G */
+               rtlphy->txpwr_by_rate_base_5g[path][txnum][rate_section - 1] =
+                       value;
+}
+
+static u8 _rtl8822be_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw,
+                                                 u8 band, u8 path, u8 txnum,
+                                                 u8 rate_section)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 value;
+
+       if (path > RF90_PATH_D) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                        "Invalid Rf Path %d in phy_GetTxPowerByRatBase()\n",
+                        path);
+               return 0;
+       }
+
+       if (band != BAND_ON_2_4G && band != BAND_ON_5G) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                        "Invalid band %d in phy_GetTxPowerByRatBase()\n",
+                        band);
+               return 0;
+       }
+
+       if (rate_section >= MAX_RATE_SECTION ||
+           (band == BAND_ON_5G && rate_section == CCK)) {
+               RT_TRACE(
+                       rtlpriv, COMP_INIT, DBG_LOUD,
+                       "Invalid rate_section %d in phy_GetTxPowerByRatBase()\n",
+                       rate_section);
+               return 0;
+       }
+
+       if (band == BAND_ON_2_4G)
+               value = rtlphy->txpwr_by_rate_base_24g[path][txnum]
+                                                     [rate_section];
+       else /* BAND_ON_5G */
+               value = rtlphy->txpwr_by_rate_base_5g[path][txnum]
+                                                    [rate_section - 1];
+
+       return value;
+}
+
+static void _rtl8822be_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+
+       struct {
+               enum rtl_desc_rate rate;
+               enum rate_section section;
+       } rate_sec_base[] = {
+               {DESC_RATE11M, CCK},
+               {DESC_RATE54M, OFDM},
+               {DESC_RATEMCS7, HT_MCS0_MCS7},
+               {DESC_RATEMCS15, HT_MCS8_MCS15},
+               {DESC_RATEVHT1SS_MCS7, VHT_1SSMCS0_1SSMCS9},
+               {DESC_RATEVHT2SS_MCS7, VHT_2SSMCS0_2SSMCS9},
+       };
+
+       u8 band, path, rs, tx_num, base;
+       u8 rate, section;
+
+       for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) {
+               for (path = RF90_PATH_A; path <= RF90_PATH_B; path++) {
+                       for (rs = 0; rs < MAX_RATE_SECTION; rs++) {
+                               rate = rate_sec_base[rs].rate;
+                               section = rate_sec_base[rs].section;
+
+                               if (IS_1T_RATE(rate))
+                                       tx_num = RF_1TX;
+                               else
+                                       tx_num = RF_2TX;
+
+                               if (band == BAND_ON_5G &&
+                                   RX_HAL_IS_CCK_RATE(rate))
+                                       continue;
+
+                               base = rtlphy->tx_power_by_rate_offset
+                                              [band][path][tx_num][rate];
+                               _rtl8822be_phy_set_txpower_by_rate_base(
+                                       hw, band, path, section, tx_num, base);
+                       }
+               }
+       }
+}
+
+static void __rtl8822be_phy_cross_reference_core(struct ieee80211_hw *hw,
+                                                u8 regulation, u8 bw,
+                                                u8 channel)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 rs, ref_rs;
+       s8 pwrlmt, ref_pwrlmt;
+
+       for (rs = 0; rs < MAX_RATE_SECTION_NUM; ++rs) {
+               /*5G 20M 40M VHT and HT can cross reference*/
+               if (bw != HT_CHANNEL_WIDTH_20 && bw != HT_CHANNEL_WIDTH_20_40)
+                       continue;
+
+               if (rs == HT_MCS0_MCS7)
+                       ref_rs = VHT_1SSMCS0_1SSMCS9;
+               else if (rs == HT_MCS8_MCS15)
+                       ref_rs = VHT_2SSMCS0_2SSMCS9;
+               else if (rs == VHT_1SSMCS0_1SSMCS9)
+                       ref_rs = HT_MCS0_MCS7;
+               else if (rs == VHT_2SSMCS0_2SSMCS9)
+                       ref_rs = HT_MCS8_MCS15;
+               else
+                       continue;
+
+               ref_pwrlmt = rtlphy->txpwr_limit_5g[regulation][bw][ref_rs]
+                                                  [channel][RF90_PATH_A];
+               if (ref_pwrlmt == MAX_POWER_INDEX)
+                       continue;
+
+               pwrlmt = rtlphy->txpwr_limit_5g[regulation][bw][rs][channel]
+                                              [RF90_PATH_A];
+               if (pwrlmt != MAX_POWER_INDEX)
+                       continue;
+
+               rtlphy->txpwr_limit_5g[regulation][bw][rs][channel]
+                                     [RF90_PATH_A] = ref_pwrlmt;
+       }
+}
+
+static void
+_rtl8822be_phy_cross_reference_ht_and_vht_txpower_limit(struct ieee80211_hw *hw)
+{
+       u8 regulation, bw, channel;
+
+       for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) {
+               for (bw = 0; bw < MAX_5G_BANDWIDTH_NUM; ++bw) {
+                       for (channel = 0; channel < CHANNEL_MAX_NUMBER_5G;
+                            ++channel) {
+                               __rtl8822be_phy_cross_reference_core(
+                                       hw, regulation, bw, channel);
+                       }
+               }
+       }
+}
+
+static void __rtl8822be_txpwr_limit_to_index_2g(struct ieee80211_hw *hw,
+                                               u8 regulation, u8 bw,
+                                               u8 channel)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 bw40_pwr_base_dbm2_4G;
+       u8 rate_section;
+       s8 temp_pwrlmt;
+       enum rf_tx_num txnum;
+       s8 temp_value;
+       u8 rf_path;
+
+       for (rate_section = 0; rate_section < MAX_RATE_SECTION_NUM;
+            ++rate_section) {
+               /* obtain the base dBm values in 2.4G band
+                * CCK => 11M, OFDM => 54M, HT 1T => MCS7, HT 2T => MCS15
+                */
+
+               temp_pwrlmt =
+                       rtlphy->txpwr_limit_2_4g[regulation][bw][rate_section]
+                                               [channel][RF90_PATH_A];
+               txnum = IS_1T_RATESEC(rate_section) ? RF_1TX : RF_2TX;
+
+               if (temp_pwrlmt == MAX_POWER_INDEX)
+                       continue;
+
+               for (rf_path = RF90_PATH_A; rf_path < MAX_RF_PATH_NUM;
+                    ++rf_path) {
+                       bw40_pwr_base_dbm2_4G =
+                               _rtl8822be_phy_get_txpower_by_rate_base(
+                                       hw, BAND_ON_2_4G, rf_path, txnum,
+                                       rate_section);
+
+                       temp_value = temp_pwrlmt - bw40_pwr_base_dbm2_4G;
+                       rtlphy->txpwr_limit_2_4g[regulation][bw][rate_section]
+                                               [channel][rf_path] = temp_value;
+
+                       RT_TRACE(
+                               rtlpriv, COMP_INIT, DBG_TRACE,
+                               "TxPwrLimit_2_4G[regulation %d][bw %d][rateSection %d][channel %d] = %d\n(TxPwrLimit in dBm %d - BW40PwrLmt2_4G[channel %d][rfPath %d] %d)\n",
+                               regulation, bw, rate_section, channel,
+                               rtlphy->txpwr_limit_2_4g[regulation][bw]
+                                                       [rate_section][channel]
+                                                       [rf_path],
+                               (temp_pwrlmt == 63) ? 0 : temp_pwrlmt / 2,
+                               channel, rf_path, bw40_pwr_base_dbm2_4G);
+               }
+       }
+}
+
+static void __rtl8822be_txpwr_limit_to_index_5g(struct ieee80211_hw *hw,
+                                               u8 regulation, u8 bw,
+                                               u8 channel)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 bw40_pwr_base_dbm5G;
+       u8 rate_section;
+       s8 temp_pwrlmt;
+       enum rf_tx_num txnum;
+       s8 temp_value;
+       u8 rf_path;
+
+       for (rate_section = 0; rate_section < MAX_RATE_SECTION_NUM;
+            ++rate_section) {
+               /* obtain the base dBm values in 5G band
+                * OFDM => 54M, HT 1T => MCS7, HT 2T => MCS15,
+                * VHT => 1SSMCS7, VHT 2T => 2SSMCS7
+                */
+
+               temp_pwrlmt =
+                       rtlphy->txpwr_limit_5g[regulation][bw][rate_section]
+                                             [channel][RF90_PATH_A];
+               txnum = IS_1T_RATESEC(rate_section) ? RF_1TX : RF_2TX;
+
+               if (temp_pwrlmt == MAX_POWER_INDEX)
+                       continue;
+
+               for (rf_path = RF90_PATH_A; rf_path < MAX_RF_PATH_NUM;
+                    ++rf_path) {
+                       bw40_pwr_base_dbm5G =
+                               _rtl8822be_phy_get_txpower_by_rate_base(
+                                       hw, BAND_ON_5G, rf_path, txnum,
+                                       rate_section);
+
+                       temp_value = temp_pwrlmt - bw40_pwr_base_dbm5G;
+                       rtlphy->txpwr_limit_5g[regulation][bw][rate_section]
+                                             [channel][rf_path] = temp_value;
+
+                       RT_TRACE(
+                               rtlpriv, COMP_INIT, DBG_TRACE,
+                               "TxPwrLimit_5G[regulation %d][bw %d][rateSection %d][channel %d] =%d\n(TxPwrLimit in dBm %d - BW40PwrLmt5G[chnl group %d][rfPath %d] %d)\n",
+                               regulation, bw, rate_section, channel,
+                               rtlphy->txpwr_limit_5g[regulation][bw]
+                                                     [rate_section][channel]
+                                                     [rf_path],
+                               temp_pwrlmt, channel, rf_path,
+                               bw40_pwr_base_dbm5G);
+               }
+       }
+}
+
+static void
+_rtl8822be_phy_convert_txpower_limit_to_power_index(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 regulation, bw, channel;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "=====> %s()\n", __func__);
+
+       _rtl8822be_phy_cross_reference_ht_and_vht_txpower_limit(hw);
+
+       for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) {
+               for (bw = 0; bw < MAX_2_4G_BANDWIDTH_NUM; ++bw) {
+                       for (channel = 0; channel < CHANNEL_MAX_NUMBER_2G;
+                            ++channel) {
+                               __rtl8822be_txpwr_limit_to_index_2g(
+                                       hw, regulation, bw, channel);
+                       }
+               }
+       }
+
+       for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) {
+               for (bw = 0; bw < MAX_5G_BANDWIDTH_NUM; ++bw) {
+                       for (channel = 0; channel < CHANNEL_MAX_NUMBER_5G;
+                            ++channel) {
+                               __rtl8822be_txpwr_limit_to_index_5g(
+                                       hw, regulation, bw, channel);
+                       }
+               }
+       }
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<===== %s()\n", __func__);
+}
+
+static void _rtl8822be_phy_init_txpower_limit(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 i, j, k, l, m;
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "=====> %s()!\n", __func__);
+
+       for (i = 0; i < MAX_REGULATION_NUM; ++i) {
+               for (j = 0; j < MAX_2_4G_BANDWIDTH_NUM; ++j)
+                       for (k = 0; k < MAX_RATE_SECTION_NUM; ++k)
+                               for (m = 0; m < CHANNEL_MAX_NUMBER_2G; ++m)
+                                       for (l = 0; l < MAX_RF_PATH_NUM; ++l)
+                                               rtlphy->txpwr_limit_2_4g[i][j]
+                                                                       [k][m]
+                                                                       [l] =
+                                                       MAX_POWER_INDEX;
+       }
+       for (i = 0; i < MAX_REGULATION_NUM; ++i) {
+               for (j = 0; j < MAX_5G_BANDWIDTH_NUM; ++j)
+                       for (k = 0; k < MAX_RATE_SECTION_NUM; ++k)
+                               for (m = 0; m < CHANNEL_MAX_NUMBER_5G; ++m)
+                                       for (l = 0; l < MAX_RF_PATH_NUM; ++l)
+                                               rtlphy->txpwr_limit_5g[i][j][k]
+                                                                     [m][l] =
+                                                       MAX_POWER_INDEX;
+       }
+
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<===== %s()!\n", __func__);
+}
+
+static void
+_rtl8822be_phy_convert_txpower_dbm_to_relative_value(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+
+       u8 base = 0, i = 0, value = 0, band = 0, path = 0, txnum = 0;
+
+       for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) {
+               for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) {
+                       for (txnum = RF_1TX; txnum <= RF_2TX; ++txnum) {
+                               /* CCK */
+                               base = rtlphy->tx_power_by_rate_offset
+                                              [band][path][txnum]
+                                              [DESC_RATE11M];
+                               for (i = 0; i < sizeof(cck_rates); ++i) {
+                                       value = rtlphy->tx_power_by_rate_offset
+                                                       [band][path][txnum]
+                                                       [cck_rates[i]];
+                                       rtlphy->tx_power_by_rate_offset
+                                               [band][path][txnum]
+                                               [cck_rates[i]] = value - base;
+                               }
+
+                               /* OFDM */
+                               base = rtlphy->tx_power_by_rate_offset
+                                              [band][path][txnum]
+                                              [DESC_RATE54M];
+                               for (i = 0; i < sizeof(ofdm_rates); ++i) {
+                                       value = rtlphy->tx_power_by_rate_offset
+                                                       [band][path][txnum]
+                                                       [ofdm_rates[i]];
+                                       rtlphy->tx_power_by_rate_offset
+                                               [band][path][txnum]
+                                               [ofdm_rates[i]] = value - base;
+                               }
+
+                               /* HT MCS0~7 */
+                               base = rtlphy->tx_power_by_rate_offset
+                                              [band][path][txnum]
+                                              [DESC_RATEMCS7];
+                               for (i = 0; i < sizeof(ht_rates_1t); ++i) {
+                                       value = rtlphy->tx_power_by_rate_offset
+                                                       [band][path][txnum]
+                                                       [ht_rates_1t[i]];
+                                       rtlphy->tx_power_by_rate_offset
+                                               [band][path][txnum]
+                                               [ht_rates_1t[i]] = value - base;
+                               }
+
+                               /* HT MCS8~15 */
+                               base = rtlphy->tx_power_by_rate_offset
+                                              [band][path][txnum]
+                                              [DESC_RATEMCS15];
+                               for (i = 0; i < sizeof(ht_rates_2t); ++i) {
+                                       value = rtlphy->tx_power_by_rate_offset
+                                                       [band][path][txnum]
+                                                       [ht_rates_2t[i]];
+                                       rtlphy->tx_power_by_rate_offset
+                                               [band][path][txnum]
+                                               [ht_rates_2t[i]] = value - base;
+                               }
+
+                               /* VHT 1SS */
+                               base = rtlphy->tx_power_by_rate_offset
+                                              [band][path][txnum]
+                                              [DESC_RATEVHT1SS_MCS7];
+                               for (i = 0; i < sizeof(vht_rates_1t); ++i) {
+                                       value = rtlphy->tx_power_by_rate_offset
+                                                       [band][path][txnum]
+                                                       [vht_rates_1t[i]];
+                                       rtlphy->tx_power_by_rate_offset
+                                               [band][path][txnum]
+                                               [vht_rates_1t[i]] =
+                                               value - base;
+                               }
+
+                               /* VHT 2SS */
+                               base = rtlphy->tx_power_by_rate_offset
+                                              [band][path][txnum]
+                                              [DESC_RATEVHT2SS_MCS7];
+                               for (i = 0; i < sizeof(vht_rates_2t); ++i) {
+                                       value = rtlphy->tx_power_by_rate_offset
+                                                       [band][path][txnum]
+                                                       [vht_rates_2t[i]];
+                                       rtlphy->tx_power_by_rate_offset
+                                               [band][path][txnum]
+                                               [vht_rates_2t[i]] =
+                                               value - base;
+                               }
+                       }
+               }
+       }
+
+       RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, "<===%s()\n", __func__);
+}
+
+static void
+_rtl8822be_phy_txpower_by_rate_configuration(struct ieee80211_hw *hw)
+{
+       /* copy rate_section from
+        * tx_power_by_rate_offset[][rate] to txpwr_by_rate_base_24g/_5g[][rs]
+        */
+       _rtl8822be_phy_store_txpower_by_rate_base(hw);
+
+       /* convert tx_power_by_rate_offset[] to relative value */
+       _rtl8822be_phy_convert_txpower_dbm_to_relative_value(hw);
+}
+
+/* string is in decimal */
+static bool _rtl8822be_get_integer_from_string(char *str, u8 *pint)
+{
+       u16 i = 0;
+       *pint = 0;
+
+       while (str[i] != '\0') {
+               if (str[i] >= '0' && str[i] <= '9') {
+                       *pint *= 10;
+                       *pint += (str[i] - '0');
+               } else {
+                       return false;
+               }
+               ++i;
+       }
+
+       return true;
+}
+
+static bool _rtl8822be_eq_n_byte(u8 *str1, u8 *str2, u32 num)
+{
+       if (num == 0)
+               return false;
+       while (num > 0) {
+               num--;
+               if (str1[num] != str2[num])
+                       return false;
+       }
+       return true;
+}
+
+static char _rtl8822be_phy_get_chnl_idx_of_txpwr_lmt(struct ieee80211_hw *hw,
+                                                    u8 band, u8 channel)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       char channel_index = -1;
+       u8 i = 0;
+
+       if (band == BAND_ON_2_4G) {
+               channel_index = channel - 1;
+       } else if (band == BAND_ON_5G) {
+               for (i = 0; i < sizeof(rtl_channel5g) / sizeof(u8); ++i) {
+                       if (rtl_channel5g[i] == channel)
+                               channel_index = i;
+               }
+       } else {
+               RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid Band %d in %s",
+                        band, __func__);
+       }
+
+       if (channel_index == -1)
+               RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+                        "Invalid Channel %d of Band %d in %s", channel, band,
+                        __func__);
+
+       return channel_index;
+}
+
+void rtl8822be_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregulation,
+                                    u8 *pband, u8 *pbandwidth,
+                                    u8 *prate_section, u8 *prf_path,
+                                    u8 *pchannel, u8 *ppower_limit)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 regulation = 0, bandwidth = 0, rate_section = 0, channel;
+       u8 channel_index;
+       char power_limit = 0, prev_power_limit, ret;
+
+       if (!_rtl8822be_get_integer_from_string((char *)pchannel, &channel) ||
+           !_rtl8822be_get_integer_from_string((char *)ppower_limit,
+                                               &power_limit)) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+                        "Illegal index of pwr_lmt table [chnl %d][val %d]\n",
+                        channel, power_limit);
+       }
+
+       power_limit =
+               power_limit > MAX_POWER_INDEX ? MAX_POWER_INDEX : power_limit;
+
+       if (_rtl8822be_eq_n_byte(pregulation, (u8 *)("FCC"), 3))
+               regulation = 0;
+       else if (_rtl8822be_eq_n_byte(pregulation, (u8 *)("MKK"), 3))
+               regulation = 1;
+       else if (_rtl8822be_eq_n_byte(pregulation, (u8 *)("ETSI"), 4))
+               regulation = 2;
+       else if (_rtl8822be_eq_n_byte(pregulation, (u8 *)("WW13"), 4))
+               regulation = 3;
+
+       if (_rtl8822be_eq_n_byte(prate_section, (u8 *)("CCK"), 3))
+               rate_section = CCK;
+       else if (_rtl8822be_eq_n_byte(prate_section, (u8 *)("OFDM"), 4))
+               rate_section = OFDM;
+       else if (_rtl8822be_eq_n_byte(prate_section, (u8 *)("HT"), 2) &&
+                _rtl8822be_eq_n_byte(prf_path, (u8 *)("1T"), 2))
+               rate_section = HT_MCS0_MCS7;
+       else if (_rtl8822be_eq_n_byte(prate_section, (u8 *)("HT"), 2) &&
+                _rtl8822be_eq_n_byte(prf_path, (u8 *)("2T"), 2))
+               rate_section = HT_MCS8_MCS15;
+       else if (_rtl8822be_eq_n_byte(prate_section, (u8 *)("VHT"), 3) &&
+                _rtl8822be_eq_n_byte(prf_path, (u8 *)("1T"), 2))
+               rate_section = VHT_1SSMCS0_1SSMCS9;
+       else if (_rtl8822be_eq_n_byte(prate_section, (u8 *)("VHT"), 3) &&
+                _rtl8822be_eq_n_byte(prf_path, (u8 *)("2T"), 2))
+               rate_section = VHT_2SSMCS0_2SSMCS9;
+
+       if (_rtl8822be_eq_n_byte(pbandwidth, (u8 *)("20M"), 3))
+               bandwidth = HT_CHANNEL_WIDTH_20;
+       else if (_rtl8822be_eq_n_byte(pbandwidth, (u8 *)("40M"), 3))
+               bandwidth = HT_CHANNEL_WIDTH_20_40;
+       else if (_rtl8822be_eq_n_byte(pbandwidth, (u8 *)("80M"), 3))
+               bandwidth = HT_CHANNEL_WIDTH_80;
+       else if (_rtl8822be_eq_n_byte(pbandwidth, (u8 *)("160M"), 4))
+               bandwidth = 3;
+
+       if (_rtl8822be_eq_n_byte(pband, (u8 *)("2.4G"), 4)) {
+               ret = _rtl8822be_phy_get_chnl_idx_of_txpwr_lmt(hw, BAND_ON_2_4G,
+                                                              channel);
+
+               if (ret == -1)
+                       return;
+
+               channel_index = ret;
+
+               prev_power_limit =
+                       rtlphy->txpwr_limit_2_4g[regulation][bandwidth]
+                                               [rate_section][channel_index]
+                                               [RF90_PATH_A];
+
+               if (power_limit < prev_power_limit)
+                       rtlphy->txpwr_limit_2_4g[regulation][bandwidth]
+                                               [rate_section][channel_index]
+                                               [RF90_PATH_A] = power_limit;
+
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+                        "2.4G [regula %d][bw %d][sec %d][chnl %d][val %d]\n",
+                        regulation, bandwidth, rate_section, channel_index,
+                        rtlphy->txpwr_limit_2_4g[regulation][bandwidth]
+                                                [rate_section][channel_index]
+                                                [RF90_PATH_A]);
+       } else if (_rtl8822be_eq_n_byte(pband, (u8 *)("5G"), 2)) {
+               ret = _rtl8822be_phy_get_chnl_idx_of_txpwr_lmt(hw, BAND_ON_5G,
+                                                              channel);
+
+               if (ret == -1)
+                       return;
+
+               channel_index = ret;
+
+               prev_power_limit =
+                       rtlphy->txpwr_limit_5g[regulation][bandwidth]
+                                             [rate_section][channel_index]
+                                             [RF90_PATH_A];
+
+               if (power_limit < prev_power_limit)
+                       rtlphy->txpwr_limit_5g[regulation][bandwidth]
+                                             [rate_section][channel_index]
+                                             [RF90_PATH_A] = power_limit;
+
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+                        "5G: [regul %d][bw %d][sec %d][chnl %d][val %d]\n",
+                        regulation, bandwidth, rate_section, channel,
+                        rtlphy->txpwr_limit_5g[regulation][bandwidth]
+                                              [rate_section][channel_index]
+                                              [RF90_PATH_A]);
+
+       } else {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+                        "Cannot recognize the band info in %s\n", pband);
+               return;
+       }
+}
+
+bool rtl8822be_load_txpower_by_rate(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       bool rtstatus = true;
+
+       _rtl8822be_phy_init_tx_power_by_rate(hw);
+
+       rtstatus = rtlpriv->phydm.ops->phydm_load_txpower_by_rate(rtlpriv);
+
+       if (!rtstatus) {
+               pr_err("BB_PG Reg Fail!!");
+               return false;
+       }
+
+       _rtl8822be_phy_txpower_by_rate_configuration(hw);
+
+       return true;
+}
+
+bool rtl8822be_load_txpower_limit(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
+       bool rtstatus = true;
+
+       _rtl8822be_phy_init_txpower_limit(hw);
+
+       if (rtlefuse->eeprom_regulatory == 1)
+               ;
+       else
+               return true;
+
+       rtstatus = rtlpriv->phydm.ops->phydm_load_txpower_limit(rtlpriv);
+
+       if (!rtstatus) {
+               pr_err("RF TxPwr Limit Fail!!");
+               return false;
+       }
+
+       _rtl8822be_phy_convert_txpower_limit_to_power_index(hw);
+
+       return true;
+}
+
+static void _rtl8822be_get_rate_values_of_tx_power_by_rate(
+       struct ieee80211_hw *hw, u32 reg_addr, u32 bit_mask, u32 value,
+       u8 *rate, s8 *pwr_by_rate_val, u8 *rate_num)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 /*index = 0,*/ i = 0;
+
+       switch (reg_addr) {
+       case 0xE00: /*rTxAGC_A_Rate18_06:*/
+       case 0x830: /*rTxAGC_B_Rate18_06:*/
+               rate[0] = DESC_RATE6M;
+               rate[1] = DESC_RATE9M;
+               rate[2] = DESC_RATE12M;
+               rate[3] = DESC_RATE18M;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xE04: /*rTxAGC_A_Rate54_24:*/
+       case 0x834: /*rTxAGC_B_Rate54_24:*/
+               rate[0] = DESC_RATE24M;
+               rate[1] = DESC_RATE36M;
+               rate[2] = DESC_RATE48M;
+               rate[3] = DESC_RATE54M;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xE08: /*rTxAGC_A_CCK1_Mcs32:*/
+               rate[0] = DESC_RATE1M;
+               pwr_by_rate_val[0] = (s8)((((value >> (8 + 4)) & 0xF)) * 10 +
+                                         ((value >> 8) & 0xF));
+               *rate_num = 1;
+               break;
+
+       case 0x86C: /*rTxAGC_B_CCK11_A_CCK2_11:*/
+               if (bit_mask == 0xffffff00) {
+                       rate[0] = DESC_RATE2M;
+                       rate[1] = DESC_RATE5_5M;
+                       rate[2] = DESC_RATE11M;
+                       for (i = 1; i < 4; ++i) {
+                               pwr_by_rate_val[i - 1] = (s8)(
+                                       (((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                       ((value >> (i * 8)) & 0xF));
+                       }
+                       *rate_num = 3;
+               } else if (bit_mask == 0x000000ff) {
+                       rate[0] = DESC_RATE11M;
+                       pwr_by_rate_val[0] = (s8)((((value >> 4) & 0xF)) * 10 +
+                                                 (value & 0xF));
+                       *rate_num = 1;
+               }
+               break;
+
+       case 0xE10: /*rTxAGC_A_Mcs03_Mcs00:*/
+       case 0x83C: /*rTxAGC_B_Mcs03_Mcs00:*/
+               rate[0] = DESC_RATEMCS0;
+               rate[1] = DESC_RATEMCS1;
+               rate[2] = DESC_RATEMCS2;
+               rate[3] = DESC_RATEMCS3;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xE14: /*rTxAGC_A_Mcs07_Mcs04:*/
+       case 0x848: /*rTxAGC_B_Mcs07_Mcs04:*/
+               rate[0] = DESC_RATEMCS4;
+               rate[1] = DESC_RATEMCS5;
+               rate[2] = DESC_RATEMCS6;
+               rate[3] = DESC_RATEMCS7;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xE18: /*rTxAGC_A_Mcs11_Mcs08:*/
+       case 0x84C: /*rTxAGC_B_Mcs11_Mcs08:*/
+               rate[0] = DESC_RATEMCS8;
+               rate[1] = DESC_RATEMCS9;
+               rate[2] = DESC_RATEMCS10;
+               rate[3] = DESC_RATEMCS11;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xE1C: /*rTxAGC_A_Mcs15_Mcs12:*/
+       case 0x868: /*rTxAGC_B_Mcs15_Mcs12:*/
+               rate[0] = DESC_RATEMCS12;
+               rate[1] = DESC_RATEMCS13;
+               rate[2] = DESC_RATEMCS14;
+               rate[3] = DESC_RATEMCS15;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+
+               break;
+
+       case 0x838: /*rTxAGC_B_CCK1_55_Mcs32:*/
+               rate[0] = DESC_RATE1M;
+               rate[1] = DESC_RATE2M;
+               rate[2] = DESC_RATE5_5M;
+               for (i = 1; i < 4; ++i) {
+                       pwr_by_rate_val[i - 1] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 3;
+               break;
+
+       case 0xC20:
+       case 0xE20:
+       case 0x1820:
+       case 0x1a20:
+               rate[0] = DESC_RATE1M;
+               rate[1] = DESC_RATE2M;
+               rate[2] = DESC_RATE5_5M;
+               rate[3] = DESC_RATE11M;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC24:
+       case 0xE24:
+       case 0x1824:
+       case 0x1a24:
+               rate[0] = DESC_RATE6M;
+               rate[1] = DESC_RATE9M;
+               rate[2] = DESC_RATE12M;
+               rate[3] = DESC_RATE18M;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC28:
+       case 0xE28:
+       case 0x1828:
+       case 0x1a28:
+               rate[0] = DESC_RATE24M;
+               rate[1] = DESC_RATE36M;
+               rate[2] = DESC_RATE48M;
+               rate[3] = DESC_RATE54M;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC2C:
+       case 0xE2C:
+       case 0x182C:
+       case 0x1a2C:
+               rate[0] = DESC_RATEMCS0;
+               rate[1] = DESC_RATEMCS1;
+               rate[2] = DESC_RATEMCS2;
+               rate[3] = DESC_RATEMCS3;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC30:
+       case 0xE30:
+       case 0x1830:
+       case 0x1a30:
+               rate[0] = DESC_RATEMCS4;
+               rate[1] = DESC_RATEMCS5;
+               rate[2] = DESC_RATEMCS6;
+               rate[3] = DESC_RATEMCS7;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC34:
+       case 0xE34:
+       case 0x1834:
+       case 0x1a34:
+               rate[0] = DESC_RATEMCS8;
+               rate[1] = DESC_RATEMCS9;
+               rate[2] = DESC_RATEMCS10;
+               rate[3] = DESC_RATEMCS11;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC38:
+       case 0xE38:
+       case 0x1838:
+       case 0x1a38:
+               rate[0] = DESC_RATEMCS12;
+               rate[1] = DESC_RATEMCS13;
+               rate[2] = DESC_RATEMCS14;
+               rate[3] = DESC_RATEMCS15;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC3C:
+       case 0xE3C:
+       case 0x183C:
+       case 0x1a3C:
+               rate[0] = DESC_RATEVHT1SS_MCS0;
+               rate[1] = DESC_RATEVHT1SS_MCS1;
+               rate[2] = DESC_RATEVHT1SS_MCS2;
+               rate[3] = DESC_RATEVHT1SS_MCS3;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC40:
+       case 0xE40:
+       case 0x1840:
+       case 0x1a40:
+               rate[0] = DESC_RATEVHT1SS_MCS4;
+               rate[1] = DESC_RATEVHT1SS_MCS5;
+               rate[2] = DESC_RATEVHT1SS_MCS6;
+               rate[3] = DESC_RATEVHT1SS_MCS7;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC44:
+       case 0xE44:
+       case 0x1844:
+       case 0x1a44:
+               rate[0] = DESC_RATEVHT1SS_MCS8;
+               rate[1] = DESC_RATEVHT1SS_MCS9;
+               rate[2] = DESC_RATEVHT2SS_MCS0;
+               rate[3] = DESC_RATEVHT2SS_MCS1;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC48:
+       case 0xE48:
+       case 0x1848:
+       case 0x1a48:
+               rate[0] = DESC_RATEVHT2SS_MCS2;
+               rate[1] = DESC_RATEVHT2SS_MCS3;
+               rate[2] = DESC_RATEVHT2SS_MCS4;
+               rate[3] = DESC_RATEVHT2SS_MCS5;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       case 0xC4C:
+       case 0xE4C:
+       case 0x184C:
+       case 0x1a4C:
+               rate[0] = DESC_RATEVHT2SS_MCS6;
+               rate[1] = DESC_RATEVHT2SS_MCS7;
+               rate[2] = DESC_RATEVHT2SS_MCS8;
+               rate[3] = DESC_RATEVHT2SS_MCS9;
+               for (i = 0; i < 4; ++i) {
+                       pwr_by_rate_val[i] =
+                               (s8)((((value >> (i * 8 + 4)) & 0xF)) * 10 +
+                                    ((value >> (i * 8)) & 0xF));
+               }
+               *rate_num = 4;
+               break;
+
+       default:
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+                        "Invalid reg_addr 0x%x in %s()\n", reg_addr, __func__);
+               break;
+       };
+}
+
+void rtl8822be_store_tx_power_by_rate(struct ieee80211_hw *hw, u32 band,
+                                     u32 rfpath, u32 txnum, u32 regaddr,
+                                     u32 bitmask, u32 data)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 i = 0, rates[4] = {0}, rate_num = 0;
+       s8 pwr_by_rate_val[4] = {0};
+
+       _rtl8822be_get_rate_values_of_tx_power_by_rate(
+               hw, regaddr, bitmask, data, rates, pwr_by_rate_val, &rate_num);
+
+       if (band != BAND_ON_2_4G && band != BAND_ON_5G) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n",
+                        band);
+               band = BAND_ON_2_4G;
+       }
+       if (rfpath >= MAX_RF_PATH) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n",
+                        rfpath);
+               rfpath = MAX_RF_PATH - 1;
+       }
+       if (txnum >= MAX_RF_PATH) {
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n",
+                        txnum);
+               txnum = MAX_RF_PATH - 1;
+       }
+
+       for (i = 0; i < rate_num; ++i) {
+               u8 rate_idx = rates[i];
+
+               if (IS_1T_RATE(rates[i]))
+                       txnum = RF_1TX;
+               else if (IS_2T_RATE(rates[i]))
+                       txnum = RF_2TX;
+               else
+                       WARN_ON(1);
+
+               rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_idx] =
+                       pwr_by_rate_val[i];
+
+               RT_TRACE(
+                       rtlpriv, COMP_INIT, DBG_LOUD,
+                       "TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][rate_idx %d] = 0x%x\n",
+                       band, rfpath, txnum, rate_idx,
+                       rtlphy->tx_power_by_rate_offset[band][rfpath][txnum]
+                                                      [rate_idx]);
+       }
+}
+
+static void
+_rtl8822be_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+
+       rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+       rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+
+       rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
+       rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
+
+       rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
+       rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
+
+       rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = RA_LSSIWRITE_8822B;
+       rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = RB_LSSIWRITE_8822B;
+
+       rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RHSSIREAD_8822BE;
+       rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RHSSIREAD_8822BE;
+
+       rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RA_SIREAD_8822B;
+       rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RB_SIREAD_8822B;
+
+       rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = RA_PIREAD_8822B;
+       rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = RB_PIREAD_8822B;
+}
+
+void rtl8822be_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 txpwr_level;
+       long txpwr_dbm;
+
+       txpwr_level = rtlphy->cur_cck_txpwridx;
+       txpwr_dbm = _rtl8822be_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_B,
+                                                   txpwr_level);
+       txpwr_level = rtlphy->cur_ofdm24g_txpwridx;
+       if (_rtl8822be_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, txpwr_level) >
+           txpwr_dbm)
+               txpwr_dbm = _rtl8822be_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G,
+                                                           txpwr_level);
+       txpwr_level = rtlphy->cur_ofdm24g_txpwridx;
+       if (_rtl8822be_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G,
+                                           txpwr_level) > txpwr_dbm)
+               txpwr_dbm = _rtl8822be_phy_txpwr_idx_to_dbm(
+                       hw, WIRELESS_MODE_N_24G, txpwr_level);
+       *powerlevel = txpwr_dbm;
+}
+
+static bool _rtl8822be_phy_get_chnl_index(u8 channel, u8 *chnl_index)
+{
+       u8 rtl_channel5g[CHANNEL_MAX_NUMBER_5G] = {
+               36,  38,  40,  42,  44,  46,  48, /* Band 1 */
+               52,  54,  56,  58,  60,  62,  64, /* Band 2 */
+               100, 102, 104, 106, 108, 110, 112, /* Band 3 */
+               116, 118, 120, 122, 124, 126, 128, /* Band 3 */
+               132, 134, 136, 138, 140, 142, 144, /* Band 3 */
+               149, 151, 153, 155, 157, 159, 161, /* Band 4 */
+               165, 167, 169, 171, 173, 175, 177}; /* Band 4 */
+       u8 i = 0;
+       bool in_24g = true;
+
+       if (channel <= 14) {
+               in_24g = true;
+               *chnl_index = channel - 1;
+       } else {
+               in_24g = false;
+
+               for (i = 0; i < CHANNEL_MAX_NUMBER_5G; ++i) {
+                       if (rtl_channel5g[i] == channel) {
+                               *chnl_index = i;
+                               return in_24g;
+                       }
+               }
+       }
+       return in_24g;
+}
+
+static char _rtl8822be_phy_get_world_wide_limit(char *limit_table)
+{
+       char min = limit_table[0];
+       u8 i = 0;
+
+       for (i = 0; i < MAX_REGULATION_NUM; ++i) {
+               if (limit_table[i] < min)
+                       min = limit_table[i];
+       }
+       return min;
+}
+
+static char _rtl8822be_phy_get_txpower_limit(struct ieee80211_hw *hw, u8 band,
+                                            enum ht_channel_width bandwidth,
+                                            enum radio_path rf_path, u8 rate,
+                                            u8 channel)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       short regulation = -1, rate_section = -1, channel_index = -1;
+       char power_limit = MAX_POWER_INDEX;
+
+       if (rtlefuse->eeprom_regulatory == 2)
+               return MAX_POWER_INDEX;
+
+       regulation = TXPWR_LMT_WW;
+
+       switch (rate) {
+       case DESC_RATE1M:
+       case DESC_RATE2M:
+       case DESC_RATE5_5M:
+       case DESC_RATE11M:
+               rate_section = CCK;
+               break;
+
+       case DESC_RATE6M:
+       case DESC_RATE9M:
+       case DESC_RATE12M:
+       case DESC_RATE18M:
+       case DESC_RATE24M:
+       case DESC_RATE36M:
+       case DESC_RATE48M:
+       case DESC_RATE54M:
+               rate_section = OFDM;
+               break;
+
+       case DESC_RATEMCS0:
+       case DESC_RATEMCS1:
+       case DESC_RATEMCS2:
+       case DESC_RATEMCS3:
+       case DESC_RATEMCS4:
+       case DESC_RATEMCS5:
+       case DESC_RATEMCS6:
+       case DESC_RATEMCS7:
+               rate_section = HT_MCS0_MCS7;
+               break;
+
+       case DESC_RATEMCS8:
+       case DESC_RATEMCS9:
+       case DESC_RATEMCS10:
+       case DESC_RATEMCS11:
+       case DESC_RATEMCS12:
+       case DESC_RATEMCS13:
+       case DESC_RATEMCS14:
+       case DESC_RATEMCS15:
+               rate_section = HT_MCS8_MCS15;
+               break;
+
+       case DESC_RATEVHT1SS_MCS0:
+       case DESC_RATEVHT1SS_MCS1:
+       case DESC_RATEVHT1SS_MCS2:
+       case DESC_RATEVHT1SS_MCS3:
+       case DESC_RATEVHT1SS_MCS4:
+       case DESC_RATEVHT1SS_MCS5:
+       case DESC_RATEVHT1SS_MCS6:
+       case DESC_RATEVHT1SS_MCS7:
+       case DESC_RATEVHT1SS_MCS8:
+       case DESC_RATEVHT1SS_MCS9:
+               rate_section = VHT_1SSMCS0_1SSMCS9;
+               break;
+
+       case DESC_RATEVHT2SS_MCS0:
+       case DESC_RATEVHT2SS_MCS1:
+       case DESC_RATEVHT2SS_MCS2:
+       case DESC_RATEVHT2SS_MCS3:
+       case DESC_RATEVHT2SS_MCS4:
+       case DESC_RATEVHT2SS_MCS5:
+       case DESC_RATEVHT2SS_MCS6:
+       case DESC_RATEVHT2SS_MCS7:
+       case DESC_RATEVHT2SS_MCS8:
+       case DESC_RATEVHT2SS_MCS9:
+               rate_section = VHT_2SSMCS0_2SSMCS9;
+               break;
+
+       default:
+               RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Wrong rate 0x%x\n",
+                        rate);
+               break;
+       }
+
+       if (band == BAND_ON_5G && rate_section == 0)
+               RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+                        "Wrong rate 0x%x: No CCK in 5G Band\n", rate);
+
+       /* workaround for wrong index combination to obtain tx power limit,
+        * OFDM only exists in BW 20M
+        */
+       if (rate_section == 1)
+               bandwidth = 0;
+
+       /* workaround for wrong index combination to obtain tx power limit,
+        * CCK table will only be given in BW 20M
+        */
+       if (rate_section == 0)
+               bandwidth = 0;
+
+       /* workaround for wrong indxe combination to obtain tx power limit,
+        * HT on 80M will reference to HT on 40M
+        */
+       if ((rate_section == 2 || rate_section == 3) && band == BAND_ON_5G &&
+           bandwidth == 2)
+               bandwidth = 1;
+
+       if (band == BAND_ON_2_4G)
+               channel_index = _rtl8822be_phy_get_chnl_idx_of_txpwr_lmt(
+                       hw, BAND_ON_2_4G, channel);
+       else if (band == BAND_ON_5G)
+               channel_index = _rtl8822be_phy_get_chnl_idx_of_txpwr_lmt(
+                       hw, BAND_ON_5G, channel);
+       else if (band == BAND_ON_BOTH)
+               ; /* BAND_ON_BOTH don't care temporarily */
+
+       if (band >= BANDMAX || regulation == -1 || bandwidth == -1 ||
+           rate_section == -1 || channel_index == -1) {
+               RT_TRACE(
+                       rtlpriv, COMP_POWER, DBG_LOUD,
+                       "Wrong index value to access power limit table [band %d][regulation %d][bandwidth %d][rf_path %d][rate_section %d][chnl %d]\n",
+                       band, regulation, bandwidth, rf_path, rate_section,
+                       channel_index);
+               return MAX_POWER_INDEX;
+       }
+
+       if (band == BAND_ON_2_4G) {
+               char limits[10] = {0};
+               u8 i = 0;
+
+               for (i = 0; i < 4; ++i)
+                       limits[i] = rtlphy->txpwr_limit_2_4g[i][bandwidth]
+                                                           [rate_section]
+                                                           [channel_index]
+                                                           [rf_path];
+
+               power_limit =
+                       (regulation == TXPWR_LMT_WW) ?
+                               _rtl8822be_phy_get_world_wide_limit(limits) :
+                               rtlphy->txpwr_limit_2_4g[regulation][bandwidth]
+                                                       [rate_section]
+                                                       [channel_index]
+                                                       [rf_path];
+
+       } else if (band == BAND_ON_5G) {
+               char limits[10] = {0};
+               u8 i = 0;
+
+               for (i = 0; i < MAX_REGULATION_NUM; ++i)
+                       limits[i] =
+                               rtlphy->txpwr_limit_5g[i][bandwidth]
+                                                     [rate_section]
+                                                     [channel_index][rf_path];
+
+               power_limit =
+                       (regulation == TXPWR_LMT_WW) ?
+                               _rtl8822be_phy_get_world_wide_limit(limits) :
+                               rtlphy->txpwr_limit_5g[regulation]
+                                                     [channel_index]
+                                                     [rate_section]
+                                                     [channel_index][rf_path];
+       } else
+               RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+                        "No power limit table of the specified band\n");
+
+       return power_limit;
+}
+
+static char
+_rtl8822be_phy_get_txpower_by_rate(struct ieee80211_hw *hw, u8 band, u8 path,
+                                  u8 rate /* enum rtl_desc8822b_rate */)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 tx_num;
+       char tx_pwr_diff = 0;
+
+       if (band != BAND_ON_2_4G && band != BAND_ON_5G)
+               return tx_pwr_diff;
+
+       if (path > RF90_PATH_B)
+               return tx_pwr_diff;
+
+       if ((rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ||
+           (rate >= DESC_RATEVHT2SS_MCS0 && rate <= DESC_RATEVHT2SS_MCS9))
+               tx_num = RF_2TX;
+       else
+               tx_num = RF_1TX;
+
+       tx_pwr_diff = (char)(rtlphy->tx_power_by_rate_offset[band][path][tx_num]
+                                                           [rate] &
+                            0xff);
+
+       return tx_pwr_diff;
+}
+
+u8 rtl8822be_get_txpower_index(struct ieee80211_hw *hw, u8 path, u8 rate,
+                              u8 bandwidth, u8 channel)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+       struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+       u8 index = (channel - 1);
+       u8 txpower = 0;
+       bool in_24g = false;
+       char limit;
+       char powerdiff_byrate = 0;
+
+       if (((rtlhal->current_bandtype == BAND_ON_2_4G) &&
+            (channel > 14 || channel < 1)) ||
+           ((rtlhal->current_bandtype == BAND_ON_5G) && (channel <= 14))) {
+               index = 0;
+               RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+                        "Illegal channel!!\n");
+       }
+
+       /* 1. base tx power */
+       in_24g = _rtl8822be_phy_get_chnl_index(channel, &index);
+       if (in_24g) {
+               if (RX_HAL_IS_CCK_RATE(rate))
+                       txpower = rtlefuse->txpwrlevel_cck[path][index];
+               else if (rate >= DESC_RATE6M)
+                       txpower = rtlefuse->txpwrlevel_ht40_1s[path][index];
+               else
+                       RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+                                "invalid rate\n");
+
+               if (rate >= DESC_RATE6M && rate <= DESC_RATE54M &&
+                   !RX_HAL_IS_CCK_RATE(rate))
+                       txpower += rtlefuse->txpwr_legacyhtdiff[path][TX_1S];
+
+               if (bandwidth == HT_CHANNEL_WIDTH_20) {
+                       if ((rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT1SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower +=
+                                       rtlefuse->txpwr_ht20diff[path][TX_1S];
+                       if ((rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT2SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower +=
+                                       rtlefuse->txpwr_ht20diff[path][TX_2S];
+               } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) {
+                       if ((rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT1SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower +=
+                                       rtlefuse->txpwr_ht40diff[path][TX_1S];
+                       if ((rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT2SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower +=
+                                       rtlefuse->txpwr_ht40diff[path][TX_2S];
+               } else if (bandwidth == HT_CHANNEL_WIDTH_80) {
+                       if ((rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT1SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower +=
+                                       rtlefuse->txpwr_ht40diff[path][TX_1S];
+                       if ((rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT2SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower +=
+                                       rtlefuse->txpwr_ht40diff[path][TX_2S];
+               }
+
+       } else {
+               if (rate >= DESC_RATE6M)
+                       txpower = rtlefuse->txpwr_5g_bw40base[path][index];
+               else
+                       RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_WARNING,
+                                "INVALID Rate.\n");
+
+               if (rate >= DESC_RATE6M && rate <= DESC_RATE54M &&
+                   !RX_HAL_IS_CCK_RATE(rate))
+                       txpower += rtlefuse->txpwr_5g_ofdmdiff[path][TX_1S];
+
+               if (bandwidth == HT_CHANNEL_WIDTH_20) {
+                       if ((rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT1SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower += rtlefuse->txpwr_5g_bw20diff[path]
+                                                                     [TX_1S];
+                       if ((rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT2SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower += rtlefuse->txpwr_5g_bw20diff[path]
+                                                                     [TX_2S];
+               } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) {
+                       if ((rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT1SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower += rtlefuse->txpwr_5g_bw40diff[path]
+                                                                     [TX_1S];
+                       if ((rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT2SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower += rtlefuse->txpwr_5g_bw40diff[path]
+                                                                     [TX_2S];
+               } else if (bandwidth == HT_CHANNEL_WIDTH_80) {
+                       u8 i = 0;
+
+                       for (i = 0; i < sizeof(rtl_channel5g_80m) / sizeof(u8);
+                            ++i)
+                               if (rtl_channel5g_80m[i] == channel)
+                                       index = i;
+
+                       txpower = rtlefuse->txpwr_5g_bw80base[path][index];
+
+                       if ((rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT1SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower += rtlefuse->txpwr_5g_bw80diff[path]
+                                                                     [TX_1S];
+                       if ((rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) ||
+                           (rate >= DESC_RATEVHT2SS_MCS0 &&
+                            rate <= DESC_RATEVHT2SS_MCS9))
+                               txpower += rtlefuse->txpwr_5g_bw80diff[path]
+                                                                     [TX_2S];
+               }
+       }
+
+       /* 2. tx power by rate */
+       if (rtlefuse->eeprom_regulatory != 2)
+               powerdiff_byrate = _rtl8822be_phy_get_txpower_by_rate(
+                       hw, (u8)(!in_24g), path, rate);
+
+       /* 3. tx power limit */
+       if (rtlefuse->eeprom_regulatory == 1)
+               limit = _rtl8822be_phy_get_txpower_limit(
+                       hw, (u8)(!in_24g), bandwidth, path, rate,
+                       channel);
+       else
+               limit = MAX_POWER_INDEX;
+
+       /* ----- */
+       powerdiff_byrate = powerdiff_byrate > limit ? limit : powerdiff_byrate;
+
+       txpower += powerdiff_byrate;
+
+       if (txpower > MAX_POWER_INDEX)
+               txpower = MAX_POWER_INDEX;
+
+       return txpower;
+}
+
+static void _rtl8822be_phy_set_txpower_index(struct ieee80211_hw *hw,
+                                            u8 power_index, u8 path, u8 rate)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 shift = 0;
+       static u32 index;
+
+       /*
+       * For 8822B, phydm api use 4 bytes txagc value
+       * driver must combine every four 1 byte to one 4 byte and send to phydm
+       */
+       shift = rate & 0x03;
+       index |= ((u32)power_index << (shift * 8));
+
+       if (shift == 3) {
+               rate = rate - 3;
+
+               if (!rtlpriv->phydm.ops->phydm_write_txagc(rtlpriv, index, path,
+                                                          rate)) {
+                       RT_TRACE(rtlpriv, COMP_TXAGC, DBG_LOUD,
+                                "%s(index:%d, rfpath:%d, rate:0x%02x) fail\n",
+                                __func__, index, path, rate);
+
+                       WARN_ON(1);
+               }
+               index = 0;
+       }
+}
+
+static void _rtl8822be_phy_set_txpower_level_by_path(struct ieee80211_hw *hw,
+                                                    u8 *array, u8 path,
+                                                    u8 channel, u8 size)
+{
+       struct rtl_phy *rtlphy = &(rtl_priv(hw)->phy);
+       u8 i;
+       u8 power_index;
+
+       for (i = 0; i < size; i++) {
+               power_index = rtl8822be_get_txpower_index(
+                       hw, path, array[i], rtlphy->current_chan_bw, channel);
+               _rtl8822be_phy_set_txpower_index(hw, power_index, path,
+                                                array[i]);
+       }
+}
+
+void rtl8822be_phy_set_txpower_level_by_path(struct ieee80211_hw *hw,
+                                            u8 channel, u8 path)
+{
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+       /*
+        * Below order is *VERY* important!
+        * Because _rtl8822be_phy_set_txpower_index() do actually writing
+        * every four power values.
+        */
+       if (rtlhal->current_bandtype == BAND_ON_2_4G)
+               _rtl8822be_phy_set_txpower_level_by_path(
+                       hw, cck_rates, path, channel, sizes_of_cck_retes);
+       _rtl8822be_phy_set_txpower_level_by_path(hw, ofdm_rates, path, channel,
+                                                sizes_of_ofdm_retes);
+       _rtl8822be_phy_set_txpower_level_by_path(hw, ht_rates_1t, path, channel,
+                                                sizes_of_ht_retes_1t);
+       _rtl8822be_phy_set_txpower_level_by_path(hw, ht_rates_2t, path, channel,
+                                                sizes_of_ht_retes_2t);
+       _rtl8822be_phy_set_txpower_level_by_path(hw, vht_rates_1t, path,
+                                                channel, sizes_of_vht_retes);
+       _rtl8822be_phy_set_txpower_level_by_path(hw, vht_rates_2t, path,
+                                                channel, sizes_of_vht_retes);
+}
+
+void rtl8822be_phy_set_tx_power_index_by_rs(struct ieee80211_hw *hw, u8 channel,
+                                           u8 path, enum rate_section rs)
+{
+       struct {
+               u8 *array;
+               u8 size;
+       } rs_ref[MAX_RATE_SECTION] = {
+               {cck_rates, sizes_of_cck_retes},
+               {ofdm_rates, sizes_of_ofdm_retes},
+               {ht_rates_1t, sizes_of_ht_retes_1t},
+               {ht_rates_2t, sizes_of_ht_retes_2t},
+               {vht_rates_1t, sizes_of_vht_retes},
+               {vht_rates_2t, sizes_of_vht_retes},
+       };
+
+       if (rs >= MAX_RATE_SECTION)
+               return;
+
+       _rtl8822be_phy_set_txpower_level_by_path(hw, rs_ref[rs].array, path,
+                                                channel, rs_ref[rs].size);
+}
+
+void rtl8822be_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 path = 0;
+
+       for (path = RF90_PATH_A; path < rtlphy->num_total_rfpath; ++path)
+               rtl8822be_phy_set_txpower_level_by_path(hw, channel, path);
+}
+
+static long _rtl8822be_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
+                                           enum wireless_mode wirelessmode,
+                                           u8 txpwridx)
+{
+       long offset;
+       long pwrout_dbm;
+
+       switch (wirelessmode) {
+       case WIRELESS_MODE_B:
+               offset = -7;
+               break;
+       case WIRELESS_MODE_G:
+       case WIRELESS_MODE_N_24G:
+               offset = -8;
+               break;
+       default:
+               offset = -8;
+               break;
+       }
+       pwrout_dbm = txpwridx / 2 + offset;
+       return pwrout_dbm;
+}
+
+void rtl8822be_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       enum io_type iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN;
+
+       if (!is_hal_stop(rtlhal)) {
+               switch (operation) {
+               case SCAN_OPT_BACKUP_BAND0:
+                       iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN;
+                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
+                                                     (u8 *)&iotype);
+
+                       break;
+               case SCAN_OPT_BACKUP_BAND1:
+                       iotype = IO_CMD_PAUSE_BAND1_DM_BY_SCAN;
+                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
+                                                     (u8 *)&iotype);
+
+                       break;
+               case SCAN_OPT_RESTORE:
+                       iotype = IO_CMD_RESUME_DM_BY_SCAN;
+                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
+                                                     (u8 *)&iotype);
+                       break;
+               default:
+                       pr_err("Unknown Scan Backup operation.\n");
+                       break;
+               }
+       }
+}
+
+static u8 _rtl8822be_phy_get_pri_ch_id(struct rtl_priv *rtlpriv)
+{
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       struct rtl_mac *mac = rtl_mac(rtlpriv);
+       u8 pri_ch_idx = 0;
+
+       if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) {
+               /* primary channel is at lower subband of 80MHz & 40MHz */
+               if ((mac->cur_40_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER) &&
+                   (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER)) {
+                       pri_ch_idx = VHT_DATA_SC_20_LOWEST_OF_80MHZ;
+               /* primary channel is at
+                * lower subband of 80MHz & upper subband of 40MHz
+                */
+               } else if ((mac->cur_40_prime_sc ==
+                           HAL_PRIME_CHNL_OFFSET_UPPER) &&
+                          (mac->cur_80_prime_sc ==
+                           HAL_PRIME_CHNL_OFFSET_LOWER)) {
+                       pri_ch_idx = VHT_DATA_SC_20_LOWER_OF_80MHZ;
+               /* primary channel is at
+                * upper subband of 80MHz & lower subband of 40MHz
+                */
+               } else if ((mac->cur_40_prime_sc ==
+                         HAL_PRIME_CHNL_OFFSET_LOWER) &&
+                        (mac->cur_80_prime_sc ==
+                         HAL_PRIME_CHNL_OFFSET_UPPER)) {
+                       pri_ch_idx = VHT_DATA_SC_20_UPPER_OF_80MHZ;
+               /* primary channel is at
+                * upper subband of 80MHz & upper subband of 40MHz
+                */
+               } else if ((mac->cur_40_prime_sc ==
+                           HAL_PRIME_CHNL_OFFSET_UPPER) &&
+                          (mac->cur_80_prime_sc ==
+                           HAL_PRIME_CHNL_OFFSET_UPPER)) {
+                       pri_ch_idx = VHT_DATA_SC_20_UPPERST_OF_80MHZ;
+               } else {
+                       if (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER)
+                               pri_ch_idx = VHT_DATA_SC_40_LOWER_OF_80MHZ;
+                       else if (mac->cur_80_prime_sc ==
+                                HAL_PRIME_CHNL_OFFSET_UPPER)
+                               pri_ch_idx = VHT_DATA_SC_40_UPPER_OF_80MHZ;
+               }
+       } else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+               /* primary channel is at upper subband of 40MHz */
+               if (mac->cur_40_prime_sc == HAL_PRIME_CHNL_OFFSET_UPPER)
+                       pri_ch_idx = VHT_DATA_SC_20_UPPER_OF_80MHZ;
+               /* primary channel is at lower subband of 40MHz */
+               else if (mac->cur_40_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER)
+                       pri_ch_idx = VHT_DATA_SC_20_LOWER_OF_80MHZ;
+               else
+                       ;
+       }
+
+       return pri_ch_idx;
+}
+
+void rtl8822be_phy_set_bw_mode(struct ieee80211_hw *hw,
+                              enum nl80211_channel_type ch_type)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       u8 tmp_bw = rtlphy->current_chan_bw;
+
+       if (rtlphy->set_bwmode_inprogress)
+               return;
+       rtlphy->set_bwmode_inprogress = true;
+       if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
+               /* get primary channel index */
+               u8 pri_ch_idx = _rtl8822be_phy_get_pri_ch_id(rtlpriv);
+
+               /* 3.1 set MAC register */
+               rtlpriv->halmac.ops->halmac_set_bandwidth(
+                       rtlpriv, rtlphy->current_channel, pri_ch_idx,
+                       rtlphy->current_chan_bw);
+
+               /* 3.2 set BB/RF registet */
+               rtlpriv->phydm.ops->phydm_switch_bandwidth(
+                       rtlpriv, pri_ch_idx, rtlphy->current_chan_bw);
+
+               if (!mac->act_scanning)
+                       rtlpriv->phydm.ops->phydm_iq_calibrate(rtlpriv);
+
+               rtlphy->set_bwmode_inprogress = false;
+       } else {
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+                        "FALSE driver sleep or unload\n");
+               rtlphy->set_bwmode_inprogress = false;
+               rtlphy->current_chan_bw = tmp_bw;
+       }
+}
+
+u8 rtl8822be_phy_sw_chnl(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       u32 timeout = 1000, timecount = 0;
+       u8 channel = rtlphy->current_channel;
+
+       if (rtlphy->sw_chnl_inprogress)
+               return 0;
+       if (rtlphy->set_bwmode_inprogress)
+               return 0;
+
+       if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) {
+               RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+                        "sw_chnl_inprogress false driver sleep or unload\n");
+               return 0;
+       }
+       while (rtlphy->lck_inprogress && timecount < timeout) {
+               mdelay(50);
+               timecount += 50;
+       }
+
+       if (rtlphy->current_channel > 14)
+               rtlhal->current_bandtype = BAND_ON_5G;
+       else if (rtlphy->current_channel <= 14)
+               rtlhal->current_bandtype = BAND_ON_2_4G;
+
+       if (rtlpriv->cfg->ops->get_btc_status())
+               rtlpriv->btcoexist.btc_ops->btc_switch_band_notify(
+                       rtlpriv, rtlhal->current_bandtype, mac->act_scanning);
+       else
+               rtlpriv->btcoexist.btc_ops->btc_switch_band_notify_wifi_only(
+                       rtlpriv, rtlhal->current_bandtype, mac->act_scanning);
+
+       rtlpriv->phydm.ops->phydm_switch_band(rtlpriv, rtlphy->current_channel);
+
+       rtlphy->sw_chnl_inprogress = true;
+       if (channel == 0)
+               channel = 1;
+
+       RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+                "switch to channel%d, band type is %d\n",
+                rtlphy->current_channel, rtlhal->current_bandtype);
+
+       rtlpriv->phydm.ops->phydm_switch_channel(rtlpriv,
+                                                rtlphy->current_channel);
+
+       rtlpriv->phydm.ops->phydm_clear_txpowertracking_state(rtlpriv);
+
+       rtl8822be_phy_set_txpower_level(hw, rtlphy->current_channel);
+
+       RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n");
+       rtlphy->sw_chnl_inprogress = false;
+       return 1;
+}
+
+bool rtl8822be_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       bool postprocessing = false;
+
+       RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+                "-->IO Cmd(%#x), set_io_inprogress(%d)\n", iotype,
+                rtlphy->set_io_inprogress);
+       do {
+               switch (iotype) {
+               case IO_CMD_RESUME_DM_BY_SCAN:
+                       RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+                                "[IO CMD] Resume DM after scan.\n");
+                       postprocessing = true;
+                       break;
+               case IO_CMD_PAUSE_BAND0_DM_BY_SCAN:
+               case IO_CMD_PAUSE_BAND1_DM_BY_SCAN:
+                       RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+                                "[IO CMD] Pause DM before scan.\n");
+                       postprocessing = true;
+                       break;
+               default:
+                       pr_err("switch case not process\n");
+                       break;
+               }
+       } while (false);
+       if (postprocessing && !rtlphy->set_io_inprogress) {
+               rtlphy->set_io_inprogress = true;
+               rtlphy->current_io_type = iotype;
+       } else {
+               return false;
+       }
+       rtl8822be_phy_set_io(hw);
+       RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype);
+       return true;
+}
+
+static void rtl8822be_phy_set_io(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+
+       RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+                "--->Cmd(%#x), set_io_inprogress(%d)\n",
+                rtlphy->current_io_type, rtlphy->set_io_inprogress);
+       switch (rtlphy->current_io_type) {
+       case IO_CMD_RESUME_DM_BY_SCAN:
+               break;
+       case IO_CMD_PAUSE_BAND0_DM_BY_SCAN:
+               break;
+       case IO_CMD_PAUSE_BAND1_DM_BY_SCAN:
+               break;
+       default:
+               pr_err("switch case not process\n");
+               break;
+       }
+       rtlphy->set_io_inprogress = false;
+       RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "(%#x)\n",
+                rtlphy->current_io_type);
+}
+
+static void rtl8822be_phy_set_rf_on(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       rtl_write_byte(rtlpriv, REG_SPS0_CTRL_8822B, 0x2b);
+       rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN_8822B, 0xE3);
+       rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN_8822B, 0xE2);
+       rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN_8822B, 0xE3);
+       rtl_write_byte(rtlpriv, REG_TXPAUSE_8822B, 0x00);
+}
+
+static bool _rtl8822be_phy_set_rf_power_state(struct ieee80211_hw *hw,
+                                             enum rf_pwrstate rfpwr_state)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+       bool bresult = true;
+       u8 i, queue_id;
+       struct rtl8192_tx_ring *ring = NULL;
+
+       switch (rfpwr_state) {
+       case ERFON:
+               if ((ppsc->rfpwr_state == ERFOFF) &&
+                   RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
+                       bool rtstatus = false;
+                       u32 initialize_count = 0;
+
+                       do {
+                               initialize_count++;
+                               RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+                                        "IPS Set eRf nic enable\n");
+                               rtstatus = rtl_ps_enable_nic(hw);
+                       } while ((!rtstatus) && (initialize_count < 10));
+                       RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+               } else {
+                       RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+                                "Set ERFON slept:%d ms\n",
+                                jiffies_to_msecs(jiffies -
+                                                 ppsc->last_sleep_jiffies));
+                       ppsc->last_awake_jiffies = jiffies;
+                       rtl8822be_phy_set_rf_on(hw);
+               }
+               if (mac->link_state == MAC80211_LINKED)
+                       rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK);
+               else
+                       rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK);
+               break;
+       case ERFOFF:
+               for (queue_id = 0, i = 0;
+                    queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
+                       ring = &pcipriv->dev.tx_ring[queue_id];
+                       if (queue_id == BEACON_QUEUE ||
+                           skb_queue_len(&ring->queue) == 0) {
+                               queue_id++;
+                               continue;
+                       } else {
+                               RT_TRACE(
+                                       rtlpriv, COMP_ERR, DBG_WARNING,
+                                       "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
+                                       (i + 1), queue_id,
+                                       skb_queue_len(&ring->queue));
+
+                               udelay(10);
+                               i++;
+                       }
+                       if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+                               RT_TRACE(
+                                       rtlpriv, COMP_ERR, DBG_WARNING,
+                                       "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
+                                       MAX_DOZE_WAITING_TIMES_9x, queue_id,
+                                       skb_queue_len(&ring->queue));
+                               break;
+                       }
+               }
+
+               if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
+                       RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+                                "IPS Set eRf nic disable\n");
+                       rtl_ps_disable_nic(hw);
+                       RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+               } else {
+                       if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
+                               rtlpriv->cfg->ops->led_control(hw,
+                                                              LED_CTL_NO_LINK);
+                       } else {
+                               rtlpriv->cfg->ops->led_control(
+                                       hw, LED_CTL_POWER_OFF);
+                       }
+               }
+               break;
+       default:
+               pr_err("switch case not process\n");
+               bresult = false;
+               break;
+       }
+       if (bresult)
+               ppsc->rfpwr_state = rfpwr_state;
+       return bresult;
+}
+
+bool rtl8822be_phy_set_rf_power_state(struct ieee80211_hw *hw,
+                                     enum rf_pwrstate rfpwr_state)
+{
+       struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+       bool bresult = false;
+
+       if (rfpwr_state == ppsc->rfpwr_state)
+               return bresult;
+       bresult = _rtl8822be_phy_set_rf_power_state(hw, rfpwr_state);
+       return bresult;
+}
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8822BE_PHY_H__
+#define __RTL8822BE_PHY_H__
+
+/* It must always set to 4, otherwise read
+ * efuse table sequence will be wrong.
+ */
+#define MAX_TX_COUNT   4
+#define TX_1S  0
+#define TX_2S  1
+#define TX_3S  2
+#define TX_4S  3
+
+#define MAX_POWER_INDEX        0x3F
+
+#define MAX_PRECMD_CNT 16
+#define MAX_RFDEPENDCMD_CNT    16
+#define MAX_POSTCMD_CNT        16
+
+#define MAX_DOZE_WAITING_TIMES_9x 64
+
+#define RT_CANNOT_IO(hw) false
+#define HIGHPOWER_RADIOA_ARRAYLEN      22
+
+#define IQK_ADDA_REG_NUM       16
+#define IQK_BB_REG_NUM 9
+#define MAX_TOLERANCE  5
+#define IQK_DELAY_TIME 10
+#define index_mapping_NUM 15
+
+#define APK_BB_REG_NUM 5
+#define APK_AFE_REG_NUM        16
+#define APK_CURVE_REG_NUM      4
+#define PATH_NUM       2
+
+#define LOOP_LIMIT     5
+#define MAX_STALL_TIME 50
+#define ANTENNA_DIVERSITY_VALUE        0x80
+#define MAX_TXPWR_IDX_NMODE_92S        63
+#define RESET_CNT_LIMIT        3
+
+#define IQK_ADDA_REG_NUM       16
+#define IQK_MAC_REG_NUM        4
+
+#define RF6052_MAX_PATH        2
+
+#define CT_OFFSET_MAC_ADDR     0X16
+
+#define CT_OFFSET_CCK_TX_PWR_IDX       0x5A
+#define CT_OFFSET_HT401S_TX_PWR_IDX    0x60
+#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF       0x66
+#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69
+#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C
+
+#define CT_OFFSET_HT40_MAX_PWR_OFFSET  0x6F
+#define CT_OFFSET_HT20_MAX_PWR_OFFSET  0x72
+
+#define CT_OFFSET_CHANNEL_PLAH 0x75
+#define CT_OFFSET_THERMAL_METER        0x78
+#define CT_OFFSET_RF_OPTION    0x79
+#define CT_OFFSET_VERSION      0x7E
+#define CT_OFFSET_CUSTOMER_ID  0x7F
+
+#define RTL8822BE_MAX_PATH_NUM 2
+
+#define TARGET_CHNL_NUM_2G_5G_8822B    59
+
+u32 rtl8822be_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr,
+                              u32 bitmask);
+void rtl8822be_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
+                             u32 data);
+u32 rtl8822be_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+                              u32 regaddr, u32 bitmask);
+void rtl8822be_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+                             u32 regaddr, u32 bitmask, u32 data);
+bool rtl8822be_phy_bb_config(struct ieee80211_hw *hw);
+bool rtl8822be_phy_rf_config(struct ieee80211_hw *hw);
+bool rtl8822be_halmac_cb_init_mac_register(struct rtl_priv *rtlpriv);
+bool rtl8822be_halmac_cb_init_bb_rf_register(struct rtl_priv *rtlpriv);
+void rtl8822be_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel);
+void rtl8822be_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+void rtl8822be_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
+void rtl8822be_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+void rtl8822be_phy_set_bw_mode(struct ieee80211_hw *hw,
+                              enum nl80211_channel_type ch_type);
+u8 rtl8822be_phy_sw_chnl(struct ieee80211_hw *hw);
+void rtl8822be_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
+void rtl8822be_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
+void rtl8822be_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
+void rtl8822be_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl8822be_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
+bool rtl8822be_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+                                            enum radio_path rfpath);
+bool rtl8822be_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+                                            enum radio_path rfpath);
+bool rtl8822be_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
+bool rtl8822be_phy_set_rf_power_state(struct ieee80211_hw *hw,
+                                     enum rf_pwrstate rfpwr_state);
+void rtl8822be_phy_set_txpower_level_by_path(struct ieee80211_hw *hw,
+                                            u8 channel, u8 path);
+void rtl8822be_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index,
+                     u8 thermal_value, u8 threshold);
+void rtl8822be_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index,
+                     u8 thermal_value, u8 threshold);
+void rtl8822be_reset_iqk_result(struct ieee80211_hw *hw);
+
+u8 rtl8822be_get_txpower_index(struct ieee80211_hw *hw, u8 path, u8 rate,
+                              u8 bandwidth, u8 channel);
+void rtl8822be_phy_set_tx_power_index_by_rs(struct ieee80211_hw *hw, u8 channel,
+                                           u8 path, enum rate_section rs);
+void rtl8822be_store_tx_power_by_rate(struct ieee80211_hw *hw, u32 band,
+                                     u32 rfpath, u32 txnum, u32 regaddr,
+                                     u32 bitmask, u32 data);
+void rtl8822be_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregulation,
+                                    u8 *pband, u8 *pbandwidth,
+                                    u8 *prate_section, u8 *prf_path,
+                                    u8 *pchannel, u8 *ppower_limit);
+bool rtl8822be_load_txpower_by_rate(struct ieee80211_hw *hw);
+bool rtl8822be_load_txpower_limit(struct ieee80211_hw *hw);
+
+#endif
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8822B_REG_H__
+#define __RTL8822B_REG_H__
+
+#include "../halmac/halmac_reg_8822b.h"
+#include "../halmac/halmac_bit_8822b.h"
+
+#define TXPKT_BUF_SELECT       0x69
+#define RXPKT_BUF_SELECT       0xA5
+#define DISABLE_TRXPKT_BUF_ACCESS      0x0
+
+/* Page 0 */
+#define REG_LEDCFG2_8822B      0x004E /* need review */
+#define REG_SPS0_CTRL_8822B    0x0011 /* need review: swlps */
+
+#define REG_EFUSE_ACCESS_8822B (REG_PMC_DBG_CTRL2_8822B + 3) /*0x00CF*/
+#define REG_AFE_XTAL_CTRL_8822B        REG_AFE_CTRL1_8822B
+#define REG_AFE_PLL_CTRL_8822B REG_AFE_CTRL2_8822B
+
+/* Page 1 */
+
+#define MSR (REG_CR_8822B + 2)
+
+/* for MSR 0x102 */
+#define MSR_NOLINK     0x00
+#define MSR_ADHOC      0x01
+#define MSR_INFRA      0x02
+#define MSR_AP 0x03
+
+/*-----------------------------------------------------
+ *
+ *     0x0200h ~ 0x027Fh       TXDMA Configuration
+ *
+ *-----------------------------------------------------
+ */
+
+/*-----------------------------------------------------
+ *
+ *     0x0280h ~ 0x02FFh       RXDMA Configuration
+ *
+ *-----------------------------------------------------
+ */
+#define REG_RXDMA_CONTROL_8822B (REG_RXPKT_NUM_8822B + 2) /* 0x0286 */
+
+/*-----------------------------------------------------
+ *
+ *     0x0300h ~ 0x03FFh       PCIe
+ *
+ *-----------------------------------------------------
+ */
+
+/* REG_HIMR3_8822B */
+#define IMR_H2CDOK     BIT_SETH2CDOK_MASK_8822B
+
+/* spec version 11
+ *-----------------------------------------------------
+ *
+ *     0x0400h ~ 0x047Fh       Protocol Configuration
+ *
+ *-----------------------------------------------------
+ */
+
+#define REG_MAX_AGGR_NUM_8822B (REG_PROT_MODE_CTRL_8822B + 2) /*0x04CA*/
+
+/* for RRSR 0x440 */
+#define RRSR_RSC_OFFSET        21
+#define RRSR_SHORT_OFFSET      23
+#define RRSR_RSC_BW_40M        0x600000
+#define RRSR_RSC_UPSUBCHNL     0x400000
+#define RRSR_RSC_LOWSUBCHNL    0x200000
+#define RRSR_1M        BIT(0)
+#define RRSR_2M        BIT(1)
+#define RRSR_5_5M      BIT(2)
+#define RRSR_11M       BIT(3)
+#define RRSR_6M        BIT(4)
+#define RRSR_9M        BIT(5)
+#define RRSR_12M       BIT(6)
+#define RRSR_18M       BIT(7)
+#define RRSR_24M       BIT(8)
+#define RRSR_36M       BIT(9)
+#define RRSR_48M       BIT(10)
+#define RRSR_54M       BIT(11)
+#define RRSR_MCS0      BIT(12)
+#define RRSR_MCS1      BIT(13)
+#define RRSR_MCS2      BIT(14)
+#define RRSR_MCS3      BIT(15)
+#define RRSR_MCS4      BIT(16)
+#define RRSR_MCS5      BIT(17)
+#define RRSR_MCS6      BIT(18)
+#define RRSR_MCS7      BIT(19)
+
+#define RRSR_ALL_CCK (RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M)
+#define RRSR_ALL_OFDM_AG                                                       \
+       (RRSR_6M | RRSR_9M | RRSR_12M | RRSR_18M | RRSR_24M | RRSR_36M |       \
+        RRSR_48M | RRSR_54M)
+
+/*-----------------------------------------------------
+ *
+ *     0x0500h ~ 0x05FFh       EDCA Configuration
+ *
+ *-----------------------------------------------------
+ */
+
+#define REG_SIFS_TRX_8822B (REG_SIFS_8822B + 2) /*0x0516*/
+
+/*-----------------------------------------------------
+ *
+ *     0x0600h ~ 0x07FFh       WMAC Configuration
+ *
+ *-----------------------------------------------------
+ */
+
+#define RATR_1M        0x00000001
+#define RATR_2M        0x00000002
+#define RATR_55M       0x00000004
+#define RATR_11M       0x00000008
+#define RATR_6M        0x00000010
+#define RATR_9M        0x00000020
+#define RATR_12M       0x00000040
+#define RATR_18M       0x00000080
+#define RATR_24M       0x00000100
+#define RATR_36M       0x00000200
+#define RATR_48M       0x00000400
+#define RATR_54M       0x00000800
+#define RATR_MCS0      0x00001000
+#define RATR_MCS1      0x00002000
+#define RATR_MCS2      0x00004000
+#define RATR_MCS3      0x00008000
+#define RATR_MCS4      0x00010000
+#define RATR_MCS5      0x00020000
+#define RATR_MCS6      0x00040000
+#define RATR_MCS7      0x00080000
+#define RATR_MCS8      0x00100000
+#define RATR_MCS9      0x00200000
+#define RATR_MCS10     0x00400000
+#define RATR_MCS11     0x00800000
+#define RATR_MCS12     0x01000000
+#define RATR_MCS13     0x02000000
+#define RATR_MCS14     0x04000000
+#define RATR_MCS15     0x08000000
+
+#define RATE_1M        BIT(0)
+#define RATE_2M        BIT(1)
+#define RATE_5_5M      BIT(2)
+#define RATE_11M       BIT(3)
+#define RATE_6M        BIT(4)
+#define RATE_9M        BIT(5)
+#define RATE_12M       BIT(6)
+#define RATE_18M       BIT(7)
+#define RATE_24M       BIT(8)
+#define RATE_36M       BIT(9)
+#define RATE_48M       BIT(10)
+#define RATE_54M       BIT(11)
+#define RATE_MCS0      BIT(12)
+#define RATE_MCS1      BIT(13)
+#define RATE_MCS2      BIT(14)
+#define RATE_MCS3      BIT(15)
+#define RATE_MCS4      BIT(16)
+#define RATE_MCS5      BIT(17)
+#define RATE_MCS6      BIT(18)
+#define RATE_MCS7      BIT(19)
+#define RATE_MCS8      BIT(20)
+#define RATE_MCS9      BIT(21)
+#define RATE_MCS10     BIT(22)
+#define RATE_MCS11     BIT(23)
+#define RATE_MCS12     BIT(24)
+#define RATE_MCS13     BIT(25)
+#define RATE_MCS14     BIT(26)
+#define RATE_MCS15     BIT(27)
+
+/* CAM definition */
+
+#define CAM_NONE       0x0
+#define CAM_WEP40      0x01
+#define CAM_TKIP       0x02
+#define CAM_AES        0x04
+#define CAM_WEP104     0x05
+
+/*#define      TOTAL_CAM_ENTRY                         64*/
+/*#define      HALF_CAM_ENTRY                          32*/
+
+#define CAM_WRITE      BIT(16)
+#define CAM_READ       0x00000000
+#define CAM_POLLINIG   BIT(31)
+
+/*********************************************
+ *       8822BE IMR/ISR bits
+ *********************************************
+ */
+#define IMR_DISABLED   0x0
+/* IMR DW0(0x0060-0063) Bit 0-31 */
+#define IMR_TIMER2     BIT(31)
+#define IMR_TIMER1     BIT(30)
+#define IMR_PSTIMEOUT  BIT(29)
+#define IMR_GTINT4     BIT(28)
+#define IMR_GTINT3     BIT(27)
+#define IMR_TBDER      BIT(26)
+#define IMR_TBDOK      BIT(25)
+#define IMR_TSF_BIT32_TOGGLE   BIT(24)
+#define IMR_BCNDMAINT0 BIT(20)
+#define IMR_BCNDOK0    BIT(16)
+#define IMR_HSISR_IND_ON_INT   BIT(15)
+#define IMR_BCNDMAINT_E        BIT(14)
+#define IMR_ATIMEND    BIT(12)
+#define IMR_HISR1_IND_INT      BIT(11)
+#define IMR_C2HCMD     BIT(10)
+#define IMR_CPWM2      BIT(9)
+#define IMR_CPWM       BIT(8)
+#define IMR_HIGHDOK    BIT(7)
+#define IMR_MGNTDOK    BIT(6)
+#define IMR_BKDOK      BIT(5)
+#define IMR_BEDOK      BIT(4)
+#define IMR_VIDOK      BIT(3)
+#define IMR_VODOK      BIT(2)
+#define IMR_RDU        BIT(1)
+#define IMR_ROK        BIT(0)
+
+/* IMR DW1(0x00B4-00B7) Bit 0-31 */
+#define IMR_TXFIFO_TH_INT_8822B        BIT_TXFIFO_TH_INT_8822B
+#define IMR_BTON_STS_UPDATE_MASK_8822B BIT_BTON_STS_UPDATE_MASK_8822B
+#define IMR_MCUERR     BIT(28)
+#define IMR_BCNDMAINT7 BIT(27)
+#define IMR_BCNDMAINT6 BIT(26)
+#define IMR_BCNDMAINT5 BIT(25)
+#define IMR_BCNDMAINT4 BIT(24)
+#define IMR_BCNDMAINT3 BIT(23)
+#define IMR_BCNDMAINT2 BIT(22)
+#define IMR_BCNDMAINT1 BIT(21)
+#define IMR_BCNDOK7    BIT(20)
+#define IMR_BCNDOK6    BIT(19)
+#define IMR_BCNDOK5    BIT(18)
+#define IMR_BCNDOK4    BIT(17)
+#define IMR_BCNDOK3    BIT(16)
+#define IMR_BCNDOK2    BIT(15)
+#define IMR_BCNDOK1    BIT(14)
+#define IMR_ATIMEND_E  BIT(13)
+#define IMR_ATIMEND    BIT(12)
+#define IMR_TXERR      BIT(11)
+#define IMR_RXERR      BIT(10)
+#define IMR_TXFOVW     BIT(9)
+#define IMR_RXFOVW     BIT(8)
+#define IMR_CPU_MGQ_TXDONE_MSK_8822B   BIT_CPU_MGQ_TXDONE_MSK_8822B
+#define IMR_PS_TIMER_C_MSK_8822B       BIT_PS_TIMER_C_MSK_8822B
+#define IMR_PS_TIMER_B_MSK_8822B       BIT_PS_TIMER_B_MSK_8822B
+#define IMR_PS_TIMER_A_MSK_8822B       BIT_PS_TIMER_A_MSK_8822B
+#define IMR_CPUMGQ_TX_TIMER_MSK_8822B  BIT_CPUMGQ_TX_TIMER_MSK_8822B
+
+/*********************************************
+ *       8822BE EFUSE definition
+ *********************************************
+ */
+#define HWSET_MAX_SIZE 1024
+#define EFUSE_MAX_SECTION      64
+#define EFUSE_REAL_CONTENT_LEN 1024
+#define EFUSE_OOB_PROTECT_BYTES        18
+
+#define EEPROM_DEFAULT_THERMALMETER    0x12
+
+#define RTL8822B_EEPROM_ID     0x8129
+
+#define PPG_BB_GAIN_2G_TXA_OFFSET_8822B        0xEE
+#define PPG_THERMAL_OFFSET_8822B       0xEF
+
+#define EEPROM_TX_PWR_INX_8822B        0x10
+
+#define EEPROM_CHANNEL_PLAN_8822B      0xB8
+#define EEPROM_XTAL_8822B      0xB9
+#define EEPROM_THERMAL_METER_8822B     0xBA
+#define EEPROM_IQK_LCK_8822B   0xBB
+#define EEPROM_2G_5G_PA_TYPE_8822B     0xBC
+/* PATH A & PATH B */
+#define EEPROM_2G_LNA_TYPE_GAIN_SEL_AB_8822B   0xBD
+/* PATH C & PATH D */
+#define EEPROM_2G_LNA_TYPE_GAIN_SEL_CD_8822B   0xBE
+/* PATH A & PATH B */
+#define EEPROM_5G_LNA_TYPE_GAIN_SEL_AB_8822B   0xBF
+/* PATH C & PATH D */
+#define EEPROM_5G_LNA_TYPE_GAIN_SEL_CD_8822B   0xC0
+
+#define EEPROM_RF_BOARD_OPTION_8822B   0xC1
+#define EEPROM_FEATURE_OPTION_8822B    0xC2
+#define EEPROM_RF_BT_SETTING_8822B     0xC3
+#define EEPROM_VERSION_8822B   0xC4
+#define EEPROM_CUSTOM_ID_8822B 0xC5
+#define EEPROM_TX_BBSWING_2G_8822B     0xC6
+#define EEPROM_TX_PWR_CALIBRATE_RATE_8822B     0xC8
+#define EEPROM_RF_ANTENNA_OPT_8822B    0xC9
+#define EEPROM_RFE_OPTION_8822B        0xCA
+#define EEPROM_COUNTRY_CODE_8822B      0xCB
+
+#define EEPROM_VID     0xD6
+#define EEPROM_DID     0xD8
+#define EEPROM_SVID    0xDA
+#define EEPROM_SMID    0xDC
+
+/* RTL8822BU */
+#define EEPROM_MAC_ADDR_8822BU 0x107
+#define EEPROM_VID_8822BU      0x100
+#define EEPROM_PID_8822BU      0x102
+#define EEPROM_USB_OPTIONAL_FUNCTION0_8822BU   0x104
+#define EEPROM_USB_MODE_8822BU 0x06
+
+/* RTL8822BS */
+#define EEPROM_MAC_ADDR_8822BS 0x11A
+
+/* RTL8822BE */
+#define EEPROM_MAC_ADDR_8822BE 0xD0
+
+/* ------------------------- */
+
+#define STOPBECON      BIT(6)
+#define STOPHIGHT      BIT(5)
+#define STOPMGT        BIT(4)
+#define STOPVO BIT(3)
+#define STOPVI BIT(2)
+#define STOPBE BIT(1)
+#define STOPBK BIT(0)
+
+#define RCR_APPFCS     BIT(31)
+#define RCR_APP_MIC    BIT(30)
+#define RCR_APP_ICV    BIT(29)
+#define RCR_APP_PHYST_RXFF     BIT(28)
+#define RCR_APP_BA_SSN BIT(27)
+#define RCR_VHT_DACK   BIT(26)
+#define RCR_ENMBID     BIT(24)
+#define RCR_LSIGEN     BIT(23)
+#define RCR_MFBEN      BIT(22)
+#define RCR_HTC_LOC_CTRL       BIT(14)
+#define RCR_AMF        BIT(13)
+#define RCR_ACF        BIT(12)
+#define RCR_ADF        BIT(11)
+#define RCR_AICV       BIT(9)
+#define RCR_ACRC32     BIT(8)
+#define RCR_CBSSID_BCN BIT(7)
+#define RCR_CBSSID_DATA        BIT(6)
+#define RCR_CBSSID     RCR_CBSSID_DATA
+#define RCR_APWRMGT    BIT(5)
+#define RCR_ADD3       BIT(4)
+#define RCR_AB BIT(3)
+#define RCR_AM BIT(2)
+#define RCR_APM        BIT(1)
+#define RCR_AAP        BIT(0)
+#define RCR_MXDMA_OFFSET       8
+#define RCR_FIFO_OFFSET        13
+
+#define RSV_CTRL       0x001C
+#define RD_CTRL        0x0524
+
+#define REG_USB_INFO_8822B     0xFE17
+#define REG_USB_SPECIAL_OPTION_8822B   0xFE55
+#define REG_USB_DMA_AGG_TO_8822B       0xFE5B
+#define REG_USB_AGG_TO_8822B   0xFE5C
+#define REG_USB_AGG_TH_8822B   0xFE5D
+
+#define REG_USB_VID_8822B      0xFE60
+#define REG_USB_PID_8822B      0xFE62
+#define REG_USB_OPTIONAL_8822B 0xFE64
+#define REG_USB_CHIRP_K_8822B  0xFE65
+#define REG_USB_PHY_8822B      0xFE66
+#define REG_USB_MAC_ADDR_8822B 0xFE70
+#define REG_USB_HRPWM_8822B    0xFE58
+#define REG_USB_HCPWM_8822B    0xFE57
+
+#define SW18_FPWM      BIT(3)
+
+#define ISO_MD2PP      BIT(0)
+#define ISO_UA2USB     BIT(1)
+#define ISO_UD2CORE    BIT(2)
+#define ISO_PA2PCIE    BIT(3)
+#define ISO_PD2CORE    BIT(4)
+#define ISO_IP2MAC     BIT(5)
+#define ISO_DIOP       BIT(6)
+#define ISO_DIOE       BIT(7)
+#define ISO_EB2CORE    BIT(8)
+#define ISO_DIOR       BIT(9)
+
+#define PWC_EV25V      BIT(14)
+#define PWC_EV12V      BIT(15)
+
+#define FEN_BBRSTB     BIT(0)
+#define FEN_BB_GLB_RSTN        BIT(1)
+#define FEN_USBA       BIT(2)
+#define FEN_UPLL       BIT(3)
+#define FEN_USBD       BIT(4)
+#define FEN_DIO_PCIE   BIT(5)
+#define FEN_PCIEA      BIT(6)
+#define FEN_PPLL       BIT(7)
+#define FEN_PCIED      BIT(8)
+#define FEN_DIOE       BIT(9)
+#define FEN_CPUEN      BIT(10)
+#define FEN_DCORE      BIT(11)
+#define FEN_ELDR       BIT(12)
+#define FEN_DIO_RF     BIT(13)
+#define FEN_HWPDN      BIT(14)
+#define FEN_MREGEN     BIT(15)
+
+#define PFM_LDALL      BIT(0)
+#define PFM_ALDN       BIT(1)
+#define PFM_LDKP       BIT(2)
+#define PFM_WOWL       BIT(3)
+#define EN_PDN BIT(4)
+#define PDN_PL BIT(5)
+#define APFM_ONMAC     BIT(8)
+#define APFM_OFF       BIT(9)
+#define APFM_RSM       BIT(10)
+#define AFSM_HSUS      BIT(11)
+#define AFSM_PCIE      BIT(12)
+#define APDM_MAC       BIT(13)
+#define APDM_HOST      BIT(14)
+#define APDM_HPDN      BIT(15)
+#define RDY_MACON      BIT(16)
+#define SUS_HOST       BIT(17)
+#define ROP_ALD        BIT(20)
+#define ROP_PWR        BIT(21)
+#define ROP_SPS        BIT(22)
+#define SOP_MRST       BIT(25)
+#define SOP_FUSE       BIT(26)
+#define SOP_ABG        BIT(27)
+#define SOP_AMB        BIT(28)
+#define SOP_RCK        BIT(29)
+#define SOP_A8M        BIT(30)
+#define XOP_BTCK       BIT(31)
+
+#define ANAD16V_EN     BIT(0)
+#define ANA8M  BIT(1)
+#define MACSLP BIT(4)
+#define LOADER_CLK_EN  BIT(5)
+#define _80M_SSC_DIS   BIT(7)
+#define _80M_SSC_EN_HO BIT(8)
+#define PHY_SSC_RSTB   BIT(9)
+#define SEC_CLK_EN     BIT(10)
+#define MAC_CLK_EN     BIT(11)
+#define SYS_CLK_EN     BIT(12)
+#define RING_CLK_EN    BIT(13)
+
+#define BOOT_FROM_EEPROM       BIT(4)
+#define EEPROM_EN      BIT(5)
+
+#define AFE_BGEN       BIT(0)
+#define AFE_MBEN       BIT(1)
+#define MAC_ID_EN      BIT(7)
+
+#define WLOCK_ALL      BIT(0)
+#define WLOCK_00       BIT(1)
+#define WLOCK_04       BIT(2)
+#define WLOCK_08       BIT(3)
+#define WLOCK_40       BIT(4)
+#define R_DIS_PRST_0   BIT(5)
+#define R_DIS_PRST_1   BIT(6)
+#define LOCK_ALL_EN    BIT(7)
+
+#define RF_EN  BIT(0)
+#define RF_RSTB        BIT(1)
+#define RF_SDMRSTB     BIT(2)
+
+#define LDA15_EN       BIT(0)
+#define LDA15_STBY     BIT(1)
+#define LDA15_OBUF     BIT(2)
+#define LDA15_REG_VOS  BIT(3)
+#define _LDA15_VOADJ(x) (((x) & 0x7) << 4)
+
+#define LDV12_EN       BIT(0)
+#define LDV12_SDBY     BIT(1)
+#define LPLDO_HSM      BIT(2)
+#define LPLDO_LSM_DIS  BIT(3)
+#define _LDV12_VADJ(x) (((x) & 0xF) << 4)
+
+#define XTAL_EN        BIT(0)
+#define XTAL_BSEL      BIT(1)
+#define _XTAL_BOSC(x) (((x) & 0x3) << 2)
+#define _XTAL_CADJ(x) (((x) & 0xF) << 4)
+#define XTAL_GATE_USB  BIT(8)
+#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9)
+#define XTAL_GATE_AFE  BIT(11)
+#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12)
+#define XTAL_RF_GATE   BIT(14)
+#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15)
+#define XTAL_GATE_DIG  BIT(17)
+#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18)
+#define XTAL_BT_GATE   BIT(20)
+#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21)
+#define _XTAL_GPIO(x) (((x) & 0x7) << 23)
+
+#define CKDLY_AFE      BIT(26)
+#define CKDLY_USB      BIT(27)
+#define CKDLY_DIG      BIT(28)
+#define CKDLY_BT       BIT(29)
+
+#define APLL_EN        BIT(0)
+#define APLL_320_EN    BIT(1)
+#define APLL_FREF_SEL  BIT(2)
+#define APLL_EDGE_SEL  BIT(3)
+#define APLL_WDOGB     BIT(4)
+#define APLL_LPFEN     BIT(5)
+
+#define APLL_REF_CLK_13MHZ     0x1
+#define APLL_REF_CLK_19_2MHZ   0x2
+#define APLL_REF_CLK_20MHZ     0x3
+#define APLL_REF_CLK_25MHZ     0x4
+#define APLL_REF_CLK_26MHZ     0x5
+#define APLL_REF_CLK_38_4MHZ   0x6
+#define APLL_REF_CLK_40MHZ     0x7
+
+#define APLL_320EN     BIT(14)
+#define APLL_80EN      BIT(15)
+#define APLL_1MEN      BIT(24)
+
+#define ALD_EN BIT(18)
+#define EF_PD  BIT(19)
+#define EF_FLAG        BIT(31)
+
+#define EF_TRPT        BIT(7)
+#define LDOE25_EN      BIT(31)
+
+#define RSM_EN BIT(0)
+#define TIMER_EN       BIT(4)
+
+#define TRSW0EN        BIT(2)
+#define TRSW1EN        BIT(3)
+#define EROM_EN        BIT(4)
+#define EN_BT  BIT(5)
+#define EN_UART        BIT(8)
+#define UART_910       BIT(9)
+#define EN_PMAC        BIT(10)
+#define SIC_SWRST      BIT(11)
+#define EN_SIC BIT(12)
+#define SIC_23 BIT(13)
+#define EN_HDP BIT(14)
+#define SIC_LBK        BIT(15)
+
+#define LED0PL BIT(4)
+#define LED1PL BIT(12)
+#define LED0DIS        BIT(7)
+
+#define MCUFWDL_EN     BIT(0)
+#define MCUFWDL_RDY    BIT(1)
+#define FWDL_CHKSUM_RPT        BIT(2)
+#define MACINI_RDY     BIT(3)
+#define BBINI_RDY      BIT(4)
+#define RFINI_RDY      BIT(5)
+#define WINTINI_RDY    BIT(6)
+#define CPRST  BIT(23)
+
+#define XCLK_VLD       BIT(0)
+#define ACLK_VLD       BIT(1)
+#define UCLK_VLD       BIT(2)
+#define PCLK_VLD       BIT(3)
+#define PCIRSTB        BIT(4)
+#define V15_VLD        BIT(5)
+#define TRP_B15V_EN    BIT(7)
+#define SIC_IDLE       BIT(8)
+#define BD_MAC2        BIT(9)
+#define BD_MAC1        BIT(10)
+#define IC_MACPHY_MODE BIT(11)
+#define VENDOR_ID      BIT(19)
+#define PAD_HWPD_IDN   BIT(22)
+#define TRP_VAUX_EN    BIT(23)
+#define TRP_BT_EN      BIT(24)
+#define BD_PKG_SEL     BIT(25)
+#define BD_HCI_SEL     BIT(26)
+#define TYPE_ID        BIT(27)
+
+#define CHIP_VER_RTL_MASK      0xF000
+#define CHIP_VER_RTL_SHIFT     12
+
+#define REG_LBMODE_8822B (REG_CR_8822B + 3)
+
+#define HCI_TXDMA_EN   BIT(0)
+#define HCI_RXDMA_EN   BIT(1)
+#define TXDMA_EN       BIT(2)
+#define RXDMA_EN       BIT(3)
+#define PROTOCOL_EN    BIT(4)
+#define SCHEDULE_EN    BIT(5)
+#define MACTXEN        BIT(6)
+#define MACRXEN        BIT(7)
+#define ENSWBCN        BIT(8)
+#define ENSEC  BIT(9)
+
+#define _NETTYPE(x) (((x) & 0x3) << 16)
+#define MASK_NETTYPE   0x30000
+#define NT_NO_LINK     0x0
+#define NT_LINK_AD_HOC 0x1
+#define NT_LINK_AP     0x2
+#define NT_AS_AP       0x3
+
+#define _LBMODE(x) (((x) & 0xF) << 24)
+#define MASK_LBMODE    0xF000000
+#define LOOPBACK_NORMAL        0x0
+#define LOOPBACK_IMMEDIATELY   0xB
+#define LOOPBACK_MAC_DELAY     0x3
+#define LOOPBACK_PHY   0x1
+#define LOOPBACK_DMA   0x7
+
+#define GET_RX_PAGE_SIZE(value) ((value) & 0xF)
+#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4)
+#define _PSRX_MASK     0xF
+#define _PSTX_MASK     0xF0
+#define _PSRX(x) (x)
+#define _PSTX(x) ((x) << 4)
+
+#define PBP_64 0x0
+#define PBP_128        0x1
+#define PBP_256        0x2
+#define PBP_512        0x3
+#define PBP_1024       0x4
+
+#define RXDMA_ARBBW_EN BIT(0)
+#define RXSHFT_EN      BIT(1)
+#define RXDMA_AGG_EN   BIT(2)
+#define QS_VO_QUEUE    BIT(8)
+#define QS_VI_QUEUE    BIT(9)
+#define QS_BE_QUEUE    BIT(10)
+#define QS_BK_QUEUE    BIT(11)
+#define QS_MANAGER_QUEUE       BIT(12)
+#define QS_HIGH_QUEUE  BIT(13)
+
+#define HQSEL_VOQ      BIT(0)
+#define HQSEL_VIQ      BIT(1)
+#define HQSEL_BEQ      BIT(2)
+#define HQSEL_BKQ      BIT(3)
+#define HQSEL_MGTQ     BIT(4)
+#define HQSEL_HIQ      BIT(5)
+
+#define _TXDMA_HIQ_MAP(x) (((x) & 0x3) << 14)
+#define _TXDMA_MGQ_MAP(x) (((x) & 0x3) << 12)
+#define _TXDMA_BKQ_MAP(x) (((x) & 0x3) << 10)
+#define _TXDMA_BEQ_MAP(x) (((x) & 0x3) << 8)
+#define _TXDMA_VIQ_MAP(x) (((x) & 0x3) << 6)
+#define _TXDMA_VOQ_MAP(x) (((x) & 0x3) << 4)
+
+#define QUEUE_LOW      1
+#define QUEUE_NORMAL   2
+#define QUEUE_HIGH     3
+
+#define _LLT_NO_ACTIVE 0x0
+#define _LLT_WRITE_ACCESS      0x1
+#define _LLT_READ_ACCESS       0x2
+
+#define _LLT_INIT_DATA(x) ((x) & 0xFF)
+#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8)
+#define _LLT_OP(x) (((x) & 0x3) << 30)
+#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3)
+
+#define BB_WRITE_READ_MASK (BIT(31) | BIT(30))
+#define BB_WRITE_EN    BIT(30)
+#define BB_READ_EN     BIT(31)
+
+#define _HPQ(x) ((x) & 0xFF)
+#define _LPQ(x) (((x) & 0xFF) << 8)
+#define _PUBQ(x) (((x) & 0xFF) << 16)
+#define _NPQ(x) ((x) & 0xFF)
+
+#define HPQ_PUBLIC_DIS BIT(24)
+#define LPQ_PUBLIC_DIS BIT(25)
+#define LD_RQPN        BIT(31)
+
+#define BCN_VALID      BIT(16)
+#define BCN_HEAD(x) (((x) & 0xFF) << 8)
+#define BCN_HEAD_MASK  0xFF00
+
+#define BLK_DESC_NUM_SHIFT     4
+#define BLK_DESC_NUM_MASK      0xF
+
+#define DROP_DATA_EN   BIT(9)
+
+#define EN_AMPDU_RTY_NEW       BIT(7)
+
+#define _INIRTSMCS_SEL(x) ((x) & 0x3F)
+
+#define _SPEC_SIFS_CCK(x) ((x) & 0xFF)
+#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8)
+
+#define RATE_REG_BITMAP_ALL    0xFFFFF
+
+#define _RRSC_BITMAP(x) ((x) & 0xFFFFF)
+
+#define _RRSR_RSC(x) (((x) & 0x3) << 21)
+#define RRSR_RSC_RESERVED      0x0
+#define RRSR_RSC_UPPER_SUBCHANNEL      0x1
+#define RRSR_RSC_LOWER_SUBCHANNEL      0x2
+#define RRSR_RSC_DUPLICATE_MODE        0x3
+
+#define USE_SHORT_G1   BIT(20)
+
+#define _AGGLMT_MCS0(x) ((x) & 0xF)
+#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4)
+#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8)
+#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12)
+#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16)
+#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20)
+#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24)
+#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28)
+
+#define RETRY_LIMIT_SHORT_SHIFT        8
+#define RETRY_LIMIT_LONG_SHIFT 0
+
+#define _DARF_RC1(x) ((x) & 0x1F)
+#define _DARF_RC2(x) (((x) & 0x1F) << 8)
+#define _DARF_RC3(x) (((x) & 0x1F) << 16)
+#define _DARF_RC4(x) (((x) & 0x1F) << 24)
+#define _DARF_RC5(x) ((x) & 0x1F)
+#define _DARF_RC6(x) (((x) & 0x1F) << 8)
+#define _DARF_RC7(x) (((x) & 0x1F) << 16)
+#define _DARF_RC8(x) (((x) & 0x1F) << 24)
+
+#define _RARF_RC1(x) ((x) & 0x1F)
+#define _RARF_RC2(x) (((x) & 0x1F) << 8)
+#define _RARF_RC3(x) (((x) & 0x1F) << 16)
+#define _RARF_RC4(x) (((x) & 0x1F) << 24)
+#define _RARF_RC5(x) ((x) & 0x1F)
+#define _RARF_RC6(x) (((x) & 0x1F) << 8)
+#define _RARF_RC7(x) (((x) & 0x1F) << 16)
+#define _RARF_RC8(x) (((x) & 0x1F) << 24)
+
+#define AC_PARAM_TXOP_LIMIT_OFFSET     16
+#define AC_PARAM_ECW_MAX_OFFSET        12
+#define AC_PARAM_ECW_MIN_OFFSET        8
+#define AC_PARAM_AIFS_OFFSET   0
+
+#define _AIFS(x) (x)
+#define _ECW_MAX_MIN(x) ((x) << 8)
+#define _TXOP_LIMIT(x) ((x) << 16)
+
+#define _BCNIFS(x) ((x) & 0xFF)
+#define _BCNECW(x) ((((x) & 0xF)) << 8)
+
+#define _LRL(x) ((x) & 0x3F)
+#define _SRL(x) (((x) & 0x3F) << 8)
+
+#define _SIFS_CCK_CTX(x) ((x) & 0xFF)
+#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8)
+
+#define _SIFS_OFDM_CTX(x) ((x) & 0xFF)
+#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8)
+
+#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8)
+
+#define DIS_EDCA_CNT_DWN       BIT(11)
+
+#define EN_MBSSID      BIT(1)
+#define EN_TXBCN_RPT   BIT(2)
+#define EN_BCN_FUNCTION        BIT(3)
+
+#define TSFTR_RST      BIT(0)
+#define TSFTR1_RST     BIT(1)
+
+#define STOP_BCNQ      BIT(6)
+
+#define DIS_TSF_UDT0_NORMAL_CHIP       BIT(4)
+#define DIS_TSF_UDT0_TEST_CHIP BIT(5)
+
+#define ACMHW_HW_EN    BIT(0)
+#define ACMHW_BEQ_EN   BIT(1)
+#define ACMHW_VIQ_EN   BIT(2)
+#define ACMHW_VOQ_EN   BIT(3)
+#define ACMHW_BEQ_STATUS       BIT(4)
+#define ACMHW_VIQ_STATUS       BIT(5)
+#define ACMHW_VOQ_STATUS       BIT(6)
+
+#define APSDOFF        BIT(6)
+#define APSDOFF_STATUS BIT(7)
+
+#define BW_20MHZ       BIT(2)
+
+#define RATE_BITMAP_ALL        0xFFFFF
+
+#define RATE_RRSR_CCK_ONLY_1M  0xFFFF1
+
+#define TSFRST BIT(0)
+#define DIS_GCLK       BIT(1)
+#define PAD_SEL        BIT(2)
+#define PWR_ST BIT(6)
+#define PWRBIT_OW_EN   BIT(7)
+#define ACRC   BIT(8)
+#define CFENDFORM      BIT(9)
+#define ICV    BIT(10)
+
+#define AAP    BIT(0)
+#define APM    BIT(1)
+#define AM     BIT(2)
+#define AB     BIT(3)
+#define ADD3   BIT(4)
+#define APWRMGT        BIT(5)
+#define CBSSID BIT(6)
+#define CBSSID_DATA    BIT(6)
+#define CBSSID_BCN     BIT(7)
+#define ACRC32 BIT(8)
+#define AICV   BIT(9)
+#define ADF    BIT(11)
+#define ACF    BIT(12)
+#define AMF    BIT(13)
+#define HTC_LOC_CTRL   BIT(14)
+#define UC_DATA_EN     BIT(16)
+#define BM_DATA_EN     BIT(17)
+#define MFBEN  BIT(22)
+#define LSIGEN BIT(23)
+#define EN_MBID        BIT(24)
+#define APP_BASSN      BIT(27)
+#define APP_PHYSTS     BIT(28)
+#define APP_ICV        BIT(29)
+#define APP_MIC        BIT(30)
+#define APP_FCS        BIT(31)
+
+#define _MIN_SPACE(x) ((x) & 0x7)
+#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3)
+
+#define RXERR_TYPE_OFDM_PPDU   0
+#define RXERR_TYPE_OFDM_FALSE_ALARM    1
+#define RXERR_TYPE_OFDM_MPDU_OK        2
+#define RXERR_TYPE_OFDM_MPDU_FAIL      3
+#define RXERR_TYPE_CCK_PPDU    4
+#define RXERR_TYPE_CCK_FALSE_ALARM     5
+#define RXERR_TYPE_CCK_MPDU_OK 6
+#define RXERR_TYPE_CCK_MPDU_FAIL       7
+#define RXERR_TYPE_HT_PPDU     8
+#define RXERR_TYPE_HT_FALSE_ALARM      9
+#define RXERR_TYPE_HT_MPDU_TOTAL       10
+#define RXERR_TYPE_HT_MPDU_OK  11
+#define RXERR_TYPE_HT_MPDU_FAIL        12
+#define RXERR_TYPE_RX_FULL_DROP        15
+
+#define RXERR_COUNTER_MASK     0xFFFFF
+#define RXERR_RPT_RST  BIT(27)
+#define _RXERR_RPT_SEL(type) ((type) << 28)
+
+#define SCR_TX_USE_DK  BIT(0)
+#define SCR_RX_USE_DK  BIT(1)
+#define SCR_TX_ENC_ENABLE      BIT(2)
+#define SRC_RX_DEC_ENABLE      BIT(3)
+#define SCR_SK_BY_A2   BIT(4)
+#define SCR_NO_SKMC    BIT(5)
+#define SCR_TXBCUSEDK  BIT(6)
+#define SCR_RXBCUSEDK  BIT(7)
+
+#define USB_IS_HIGH_SPEED      0
+#define USB_IS_FULL_SPEED      1
+#define USB_SPEED_MASK BIT(5)
+
+#define USB_NORMAL_SIE_EP_MASK 0xF
+#define USB_NORMAL_SIE_EP_SHIFT        4
+
+#define USB_TEST_EP_MASK       0x30
+#define USB_TEST_EP_SHIFT      4
+
+#define USB_AGG_EN     BIT(3)
+
+#define MAC_ADDR_LEN   6
+#define LAST_ENTRY_OF_TX_PKT_BUFFER    175
+
+#define POLLING_LLT_THRESHOLD  20
+#define POLLING_READY_TIMEOUT_COUNT    3000
+
+#define MAX_MSS_DENSITY_2T     0x13
+#define MAX_MSS_DENSITY_1T     0x0A
+
+#define EPROM_CMD_OPERATING_MODE_MASK ((1 << 7) | (1 << 6))
+#define EPROM_CMD_CONFIG       0x3
+#define EPROM_CMD_LOAD 1
+
+#define HAL_8822B_HW_GPIO_WPS_BIT      BIT(2)
+
+/*-----------------------------------------------------
+ * BB / RF register
+ *-----------------------------------------------------
+ */
+
+#define RFPGA0_XA_HSSIPARAMETER1       0x820
+#define RFPGA0_XA_HSSIPARAMETER2       0x824
+#define RFPGA0_XB_HSSIPARAMETER1       0x828
+#define RFPGA0_XB_HSSIPARAMETER2 0x82c
+#define RCCAONSEC      0x838
+
+#define RFPGA0_XA_LSSIPARAMETER        0x840
+#define RFPGA0_XB_LSSIPARAMETER        0x844
+#define RL1PEAKTH      0x848
+
+#define RFPGA0_RFWAKEUPPARAMETER       0x850
+#define RFPGA0_RFSLEEPUPPARAMETER      0x854
+
+#define RFPGA0_XAB_SWITCHCONTROL       0x858
+#define RFPGA0_XCD_SWITCHCONTROL 0x85c
+
+#define RFPGA0_XA_RFINTERFACEOE        0x860
+#define RFC_AREA       0x860
+#define RFPGA0_XB_RFINTERFACEOE        0x864
+
+#define RFPGA0_XAB_RFINTERFACESW       0x870
+#define RFPGA0_XCD_RFINTERFACESW       0x874
+
+#define RFPGA0_XAB_RF_PARA_METER       0x878
+#define RFPGA0_XCD_RF_PARA_METER 0x87c
+
+#define RFPGA0_ANALOGPARAMETER1        0x880
+#define RFPGA0_ANALOGPARAMETER2        0x884
+#define RFPGA0_ANALOGPARAMETER3        0x888
+#define RFPGA0_ANALOGPARAMETER4 0x88c
+
+#define RFPGA0_XA_LSSIREADBACK 0x8a0
+#define RFPGA0_XB_LSSIREADBACK 0x8a4
+#define RFPGA0_XC_LSSIREADBACK 0x8a8
+/*#define      RFPGA0_XD_LSSIREADBACK                  0x8ac*/
+#define RRFMOD 0x8ac
+#define RHSSIREAD_8822BE 0x8b0
+
+#define RFPGA0_PSDREPORT 0x8b4
+#define TRANSCEIVEA_HSPI_READBACK 0x8b8
+#define TRANSCEIVEB_HSPI_READBACK 0x8bc
+/*#define      REG_SC_CNT_8822B                                0x8c4*/
+#define RADC_BUF_CLK 0x8c4
+#define RFPGA0_XAB_RFINTERFACERB 0x8e0
+#define RFPGA0_XCD_RFINTERFACERB 0x8e4
+
+/* PageB(0xB00) */
+
+/*Page C*/
+
+#define RA_TXPWRTRAING 0xc54
+#define RB_TXPWRTRAING 0xe54
+
+#define RA_LSSIWRITE_8822B 0xc90
+#define RB_LSSIWRITE_8822B 0xe90
+
+#define RA_PIREAD_8822B 0xd04
+#define RB_PIREAD_8822B 0xd44
+#define RA_SIREAD_8822B 0xd08
+#define RB_SIREAD_8822B 0xd48
+
+#define RZEBRA1_HSSIENABLE     0x0
+#define RZEBRA1_TRXENABLE1     0x1
+#define RZEBRA1_TRXENABLE2     0x2
+#define RZEBRA1_AGC    0x4
+#define RZEBRA1_CHARGEPUMP     0x5
+#define RZEBRA1_CHANNEL        0x7
+
+#define RZEBRA1_TXGAIN 0x8
+#define RZEBRA1_TXLPF  0x9
+#define RZEBRA1_RXLPF 0xb
+#define RZEBRA1_RXHPFCORNER 0xc
+
+#define RGLOBALCTRL    0
+#define RRTL8256_TXLPF 19
+#define RRTL8256_RXLPF 11
+#define RRTL8258_TXLPF 0x11
+#define RRTL8258_RXLPF 0x13
+#define RRTL8258_RSSILPF 0xa
+
+#define RF_AC  0x00
+
+#define RF_IQADJ_G1    0x01
+#define RF_IQADJ_G2    0x02
+#define RF_POW_TRSW    0x05
+
+#define RF_GAIN_RX     0x06
+#define RF_GAIN_TX     0x07
+
+#define RF_TXM_IDAC    0x08
+#define RF_BS_IQGEN    0x0F
+
+#define RF_MODE1       0x10
+#define RF_MODE2       0x11
+
+#define RF_RX_AGC_HP   0x12
+#define RF_TX_AGC      0x13
+#define RF_BIAS        0x14
+#define RF_IPA 0x15
+#define RF_POW_ABILITY 0x17
+#define RF_MODE_AG     0x18
+#define RRFCHANNEL     0x18
+#define RF_CHNLBW      0x18
+#define RF_TOP 0x19
+
+#define RF_RX_G1       0x1A
+#define RF_RX_G2       0x1B
+
+#define RF_RX_BB2      0x1C
+#define RF_RX_BB1      0x1D
+
+#define RF_RCK1        0x1E
+#define RF_RCK2        0x1F
+
+#define RF_TX_G1       0x20
+#define RF_TX_G2       0x21
+#define RF_TX_G3       0x22
+
+#define RF_TX_BB1      0x23
+#define RF_T_METER     0x42
+
+#define RF_SYN_G1      0x25
+#define RF_SYN_G2      0x26
+#define RF_SYN_G3      0x27
+#define RF_SYN_G4      0x28
+#define RF_SYN_G5      0x29
+#define RF_SYN_G6      0x2A
+#define RF_SYN_G7      0x2B
+#define RF_SYN_G8      0x2C
+
+#define RF_RCK_OS      0x30
+#define RF_TXPA_G1     0x31
+#define RF_TXPA_G2     0x32
+#define RF_TXPA_G3     0x33
+
+#define RF_TX_BIAS_A   0x35
+#define RF_TX_BIAS_D   0x36
+#define RF_LOBF_9      0x38
+#define RF_RXRF_A3     0x3C
+#define RF_TRSW        0x3F
+
+#define RF_TXRF_A2     0x41
+#define RF_TXPA_G4     0x46
+#define RF_TXPA_A4     0x4B
+
+#define RF_APK 0x63
+
+#define RF_WE_LUT      0xEF
+
+#define BBBRESETB      0x100
+#define BGLOBALRESETB  0x200
+#define BOFDMTXSTART   0x4
+#define BCCKTXSTART    0x8
+#define BCRC32DEBUG    0x100
+#define BPMACLOOPBACK  0x10
+#define BTXLSIG 0xffffff
+#define BOFDMTXRATE 0xf
+#define BOFDMTXRESERVED        0x10
+#define BOFDMTXLENGTH 0x1ffe0
+#define BOFDMTXPARITY  0x20000
+#define BTXHTSIG1 0xffffff
+#define BTXHTMCSRATE 0x7f
+#define BTXHTBW        0x80
+#define BTXHTLENGTH 0xffff00
+#define BTXHTSIG2 0xffffff
+#define BTXHTSMOOTHING 0x1
+#define BTXHTSOUNDING  0x2
+#define BTXHTRESERVED  0x4
+#define BTXHTAGGREATION        0x8
+#define BTXHTSTBC      0x30
+#define BTXHTADVANCECODING     0x40
+#define BTXHTSHORTGI   0x80
+#define BTXHTNUMBERHT_LTF      0x300
+#define BTXHTCRC8 0x3fc00
+#define BCOUNTERRESET  0x10000
+#define BNUMOFOFDMTX 0xffff
+#define BNUMOFCCKTX 0xffff0000
+#define BTXIDLEINTERVAL 0xffff
+#define BOFDMSERVICE 0xffff0000
+#define BTXMACHEADER 0xffffffff
+#define BTXDATAINIT 0xff
+#define BTXHTMODE      0x100
+#define BTXDATATYPE    0x30000
+#define BTXRANDOMSEED 0xffffffff
+#define BCCKTXPREAMBLE 0x1
+#define BCCKTXSFD 0xffff0000
+#define BCCKTXSIG 0xff
+#define BCCKTXSERVICE 0xff00
+#define BCCKLENGTHEXT  0x8000
+#define BCCKTXLENGHT 0xffff0000
+#define BCCKTXCRC16 0xffff
+#define BCCKTXSTATUS   0x1
+#define BOFDMTXSTATUS  0x2
+#define IS_BB_REG_OFFSET_92S(_offset) ((_offset >= 0x800) && (_offset <= 0xfff))
+
+#define BRFMOD 0x1
+#define BJAPANMODE     0x2
+#define BCCKTXSC       0x30
+/* Block & Path enable*/
+#define ROFDMCCKEN     0x808
+#define BCCKEN 0x10000000
+#define BOFDMEN        0x20000000
+/* Rx antenna*/
+#define RRXPATH        0x808
+#define BRXPATH 0xff
+/* Tx antenna*/
+#define RTXPATH 0x80c
+#define BTXPATH 0x0fffffff
+/* for cck rx path selection*/
+#define RCCK_RX 0xa04
+#define BCCK_RX 0x0c000000
+/* Use LSIG for VHT length*/
+#define RVHTLEN_USE_LSIG 0x8c3
+
+#define BOFDMRXADCPHASE        0x10000
+#define BOFDMTXDACPHASE        0x40000
+#define BXATXAGC 0x3f
+
+#define BXBTXAGC 0xf00
+#define BXCTXAGC 0xf000
+#define BXDTXAGC 0xf0000
+
+#define BPASTART 0xf0000000
+#define BTRSTART 0x00f00000
+#define BRFSTART 0x0000f000
+#define BBBSTART 0x000000f0
+#define BBBCCKSTART 0x0000000f
+#define BPAEND 0xf
+#define BTREND 0x0f000000
+#define BRFEND 0x000f0000
+#define BCCAMASK 0x000000f0
+#define BR2RCCAMASK 0x00000f00
+#define BHSSI_R2TDELAY 0xf8000000
+#define BHSSI_T2RDELAY 0xf80000
+#define BCONTXHSSI     0x400
+#define BIGFROMCCK     0x200
+#define BAGCADDRESS 0x3f
+#define BRXHPTX        0x7000
+#define BRXHP2RX       0x38000
+#define BRXHPCCKINI 0xc0000
+#define BAGCTXCODE 0xc00000
+#define BAGCRXCODE     0x300000
+
+#define B3WIREDATALENGTH       0x800
+#define B3WIREADDREAALENGTH    0x400
+
+#define B3WIRERFPOWERDOWN      0x1
+#define B5GPAPEPOLARITY        0x40000000
+#define B2GPAPEPOLARITY        0x80000000
+#define BRFSW_TXDEFAULTANT     0x3
+#define BRFSW_TXOPTIONANT      0x30
+#define BRFSW_RXDEFAULTANT     0x300
+#define BRFSW_RXOPTIONANT      0x3000
+#define BRFSI_3WIREDATA        0x1
+#define BRFSI_3WIRECLOCK       0x2
+#define BRFSI_3WIRELOAD        0x4
+#define BRFSI_3WIRERW  0x8
+#define BRFSI_3WIRE 0xf
+
+#define BRFSI_RFENV    0x10
+
+#define BRFSI_TRSW     0x20
+#define BRFSI_TRSWB    0x40
+#define BRFSI_ANTSW    0x100
+#define BRFSI_ANTSWB   0x200
+#define BRFSI_PAPE     0x400
+#define BRFSI_PAPE5G   0x800
+#define BBANDSELECT    0x1
+#define BHTSIG2_GI     0x80
+#define BHTSIG2_SMOOTHING      0x01
+#define BHTSIG2_SOUNDING       0x02
+#define BHTSIG2_AGGREATON      0x08
+#define BHTSIG2_STBC   0x30
+#define BHTSIG2_ADVCODING      0x40
+#define BHTSIG2_NUMOFHTLTF     0x300
+#define BHTSIG2_CRC8 0x3fc
+#define BHTSIG1_MCS 0x7f
+#define BHTSIG1_BANDWIDTH      0x80
+#define BHTSIG1_HTLENGTH 0xffff
+#define BLSIG_RATE 0xf
+#define BLSIG_RESERVED 0x10
+#define BLSIG_LENGTH 0x1fffe
+#define BLSIG_PARITY   0x20
+#define BCCKRXPHASE    0x4
+
+#define BLSSIREADADDRESS 0x7f800000
+#define BLSSIREADEDGE  0x80000000
+
+#define BLSSIREADBACKDATA 0xfffff
+
+#define BLSSIREADOKFLAG        0x1000
+#define BCCKSAMPLERATE 0x8
+#define BREGULATOR0STANDBY     0x1
+#define BREGULATORPLLSTANDBY   0x2
+#define BREGULATOR1STANDBY     0x4
+#define BPLLPOWERUP    0x8
+#define BDPLLPOWERUP   0x10
+#define BDA10POWERUP   0x20
+#define BAD7POWERUP    0x200
+#define BDA6POWERUP    0x2000
+#define BXTALPOWERUP   0x4000
+#define B40MDCLKPOWERUP        0x8000
+#define BDA6DEBUGMODE  0x20000
+#define BDA6SWING      0x380000
+
+#define BADCLKPHASE    0x4000000
+#define B80MCLKDELAY   0x18000000
+#define BAFEWATCHDOGENABLE     0x20000000
+
+#define BXTALCAP01 0xc0000000
+#define BXTALCAP23     0x3
+#define BXTALCAP92X 0x0f000000
+#define BXTALCAP 0x0f000000
+
+#define BINTDIFCLKENABLE       0x400
+#define BEXTSIGCLKENABLE       0x800
+#define BBANDGAP_MBIAS_POWERUP 0x10000
+#define BAD11SH_GAIN 0xc0000
+#define BAD11NPUT_RANGE        0x700000
+#define BAD110P_CURRENT        0x3800000
+#define BLPATH_LOOPBACK        0x4000000
+#define BQPATH_LOOPBACK        0x8000000
+#define BAFE_LOOPBACK  0x10000000
+#define BDA10_SWING 0x7e0
+#define BDA10_REVERSE  0x800
+#define BDA_CLK_SOURCE 0x1000
+#define BDA7INPUT_RANGE        0x6000
+#define BDA7_GAIN      0x38000
+#define BDA7OUTPUT_CM_MODE     0x40000
+#define BDA7INPUT_CM_MODE      0x380000
+#define BDA7CURRENT 0xc00000
+#define BREGULATOR_ADJUST      0x7000000
+#define BAD11POWERUP_ATTX      0x1
+#define BDA10PS_ATTX   0x10
+#define BAD11POWERUP_ATRX      0x100
+#define BDA10PS_ATRX   0x1000
+#define BCCKRX_AGC_FORMAT      0x200
+#define BPSDFFT_SAMPLE_POINT 0xc000
+#define BPSD_AVERAGE_NUM       0x3000
+#define BIQPATH_CONTROL 0xc00
+#define BPSD_FREQ 0x3ff
+#define BPSD_ANTENNA_PATH      0x30
+#define BPSD_IQ_SWITCH 0x40
+#define BPSD_RX_TRIGGER        0x400000
+#define BPSD_TX_TRIGGER        0x80000000
+#define BPSD_SINE_TONE_SCALE 0x7f000000
+#define BPSD_REPORT 0xffff
+
+#define BOFDM_TXSC     0x30000000
+#define BCCK_TXON      0x1
+#define BOFDM_TXON     0x2
+#define BDEBUG_PAGE 0xfff
+#define BDEBUG_ITEM 0xff
+#define BANTL  0x10
+#define BANT_NONHT     0x100
+#define BANT_HT1       0x1000
+#define BANT_HT2       0x10000
+#define BANT_HT1S1     0x100000
+#define BANT_NONHTS1   0x1000000
+
+#define BCCK_BBMODE    0x3
+#define BCCK_TXPOWERSAVING     0x80
+#define BCCK_RXPOWERSAVING     0x40
+
+#define BCCK_SIDEBAND  0x10
+
+#define BCCK_SCRAMBLE  0x8
+#define BCCK_ANTDIVERSITY      0x8000
+#define BCCK_CARRIER_RECOVERY  0x4000
+#define BCCK_TXRATE    0x3000
+#define BCCK_DCCANCEL  0x0800
+#define BCCK_ISICANCEL 0x0400
+#define BCCK_MATCH_FILTER      0x0200
+#define BCCK_EQUALIZER 0x0100
+#define BCCK_PREAMBLE_DETECT   0x800000
+#define BCCK_FAST_FALSECCA     0x400000
+#define BCCK_CH_ESTSTART       0x300000
+#define BCCK_CCA_COUNT 0x080000
+#define BCCK_CS_LIM    0x070000
+#define BCCK_BIST_MODE 0x80000000
+#define BCCK_CCAMASK   0x40000000
+#define BCCK_TX_DAC_PHASE      0x4
+#define BCCK_RX_ADC_PHASE      0x20000000
+#define BCCKR_CP_MODE  0x0100
+#define BCCK_TXDC_OFFSET 0xf0
+#define BCCK_RXDC_OFFSET 0xf
+#define BCCK_CCA_MODE 0xc000
+#define BCCK_FALSECS_LIM 0x3f00
+#define BCCK_CS_RATIO 0xc00000
+#define BCCK_CORGBIT_SEL       0x300000
+#define BCCK_PD_LIM 0x0f0000
+#define BCCK_NEWCCA    0x80000000
+#define BCCK_RXHP_OF_IG        0x8000
+#define BCCK_RXIG 0x7f00
+#define BCCK_LNA_POLARITY      0x800000
+#define BCCK_RX1ST_BAIN 0x7f0000
+#define BCCK_RF_EXTEND 0x20000000
+#define BCCK_RXAGC_SATLEVEL 0x1f000000
+#define BCCK_RXAGC_SATCOUNT 0xe0
+#define BCCK_RX_RF_SETTLE 0x1f
+#define BCCK_FIXED_RXAGC       0x8000
+#define BCCK_ANTENNA_POLARITY  0x2000
+#define BCCK_TXFILTER_TYPE 0x0c00
+#define BCCK_RXAGC_REPORTTYPE  0x0300
+#define BCCK_RXDAGC_EN 0x80000000
+#define BCCK_RXDAGC_PERIOD     0x20000000
+#define BCCK_RXDAGC_SATLEVEL 0x1f000000
+#define BCCK_TIMING_RECOVERY   0x800000
+#define BCCK_TXC0 0x3f0000
+#define BCCK_TXC1 0x3f000000
+#define BCCK_TXC2 0x3f
+#define BCCK_TXC3 0x3f00
+#define BCCK_TXC4 0x3f0000
+#define BCCK_TXC5 0x3f000000
+#define BCCK_TXC6 0x3f
+#define BCCK_TXC7 0x3f00
+#define BCCK_DEBUGPORT 0xff0000
+#define BCCK_DAC_DEBUG 0x0f000000
+#define BCCK_FALSEALARM_ENABLE 0x8000
+#define BCCK_FALSEALARM_READ   0x4000
+#define BCCK_TRSSI 0x7f
+#define BCCK_RXAGC_REPORT 0xfe
+#define BCCK_RXREPORT_ANTSEL   0x80000000
+#define BCCK_RXREPORT_MFOFF    0x40000000
+#define BCCK_RXREPORT_SQLOSS   0x20000000
+#define BCCK_RXREPORT_PKTLOSS  0x10000000
+#define BCCK_RXREPORT_LOCKEDBIT        0x08000000
+#define BCCK_RXREPORT_RATEERROR        0x04000000
+#define BCCK_RXREPORT_RXRATE   0x03000000
+#define BCCK_RXFA_COUNTER_LOWER 0xff
+#define BCCK_RXFA_COUNTER_UPPER 0xff000000
+#define BCCK_RXHPAGC_START 0xe000
+#define BCCK_RXHPAGC_FINAL 0x1c00
+#define BCCK_RXFALSEALARM_ENABLE       0x8000
+#define BCCK_FACOUNTER_FREEZE  0x4000
+#define BCCK_TXPATH_SEL        0x10000000
+#define BCCK_DEFAULT_RXPATH 0xc000000
+#define BCCK_OPTION_RXPATH     0x3000000
+
+#define BNUM_OFSTF     0x3
+#define BSHIFT_L 0xc0
+#define BGI_TH 0xc
+#define BRXPATH_A      0x1
+#define BRXPATH_B      0x2
+#define BRXPATH_C      0x4
+#define BRXPATH_D      0x8
+#define BTXPATH_A      0x1
+#define BTXPATH_B      0x2
+#define BTXPATH_C      0x4
+#define BTXPATH_D      0x8
+#define BTRSSI_FREQ    0x200
+#define BADC_BACKOFF   0x3000
+#define BDFIR_BACKOFF 0xc000
+#define BTRSSI_LATCH_PHASE     0x10000
+#define BRX_LDC_OFFSET 0xff
+#define BRX_QDC_OFFSET 0xff00
+#define BRX_DFIR_MODE  0x1800000
+#define BRX_DCNF_TYPE 0xe000000
+#define BRXIQIMB_A 0x3ff
+#define BRXIQIMB_B 0xfc00
+#define BRXIQIMB_C 0x3f0000
+#define BRXIQIMB_D 0xffc00000
+#define BDC_DC_NOTCH   0x60000
+#define BRXNB_NOTCH 0x1f000000
+#define BPD_TH 0xf
+#define BPD_TH_OPT2 0xc000
+#define BPWED_TH       0x700
+#define BIFMF_WIN_L    0x800
+#define BPD_OPTION     0x1000
+#define BMF_WIN_L 0xe000
+#define BBW_SEARCH_L   0x30000
+#define BWIN_ENH_L 0xc0000
+#define BBW_TH 0x700000
+#define BED_TH2        0x3800000
+#define BBW_OPTION     0x4000000
+#define BRADIO_TH      0x18000000
+#define BWINDOW_L 0xe0000000
+#define BSBD_OPTION    0x1
+#define BFRAME_TH 0x1c
+#define BFS_OPTION     0x60
+#define BDC_SLOPE_CHECK        0x80
+#define BFGUARD_COUNTER_DC_L 0xe00
+#define BFRAME_WEIGHT_SHORT    0x7000
+#define BSUB_TUNE 0xe00000
+#define BFRAME_DC_LENGTH 0xe000000
+#define BSBD_START_OFFSET      0x30000000
+#define BFRAME_TH_2    0x7
+#define BFRAME_GI2_TH  0x38
+#define BGI2_SYNC_EN   0x40
+#define BSARCH_SHORT_EARLY     0x300
+#define BSARCH_SHORT_LATE 0xc00
+#define BSARCH_GI2_LATE        0x70000
+#define BCFOANTSUM     0x1
+#define BCFOACC        0x2
+#define BCFOSTARTOFFSET 0xc
+#define BCFOLOOPBACK   0x70
+#define BCFOSUMWEIGHT  0x80
+#define BDAGCENABLE    0x10000
+#define BTXIQIMB_A 0x3ff
+#define BTXIQIMB_b 0xfc00
+#define BTXIQIMB_C 0x3f0000
+#define BTXIQIMB_D 0xffc00000
+#define BTXIDCOFFSET 0xff
+#define BTXIQDCOFFSET 0xff00
+#define BTXDFIRMODE    0x10000
+#define BTXPESUDO_NOISEON      0x4000000
+#define BTXPESUDO_NOISE_A 0xff
+#define BTXPESUDO_NOISE_B 0xff00
+#define BTXPESUDO_NOISE_C 0xff0000
+#define BTXPESUDO_NOISE_D 0xff000000
+#define BCCA_DROPOPTION        0x20000
+#define BCCA_DROPTHRES 0xfff00000
+#define BEDCCA_H 0xf
+#define BEDCCA_L 0xf0
+#define BLAMBDA_ED     0x300
+#define BRX_INITIALGAIN 0x7f
+#define BRX_ANTDIV_EN  0x80
+#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00
+#define BRX_HIGHPOWER_FLOW     0x8000
+#define BRX_AGC_FREEZE_THRES 0xc0000
+#define BRX_FREEZESTEP_AGC1    0x300000
+#define BRX_FREEZESTEP_AGC2 0xc00000
+#define BRX_FREEZESTEP_AGC3    0x3000000
+#define BRX_FREEZESTEP_AGC0 0xc000000
+#define BRXRSSI_CMP_EN 0x10000000
+#define BRXQUICK_AGCEN 0x20000000
+#define BRXAGC_FREEZE_THRES_MODE       0x40000000
+#define BRX_OVERFLOW_CHECKTYPE 0x80000000
+#define BRX_AGCSHIFT 0x7f
+#define BTRSW_TRI_ONLY 0x80
+#define BPOWER_THRES   0x300
+#define BRXAGC_EN      0x1
+#define BRXAGC_TOGETHER_EN     0x2
+#define BRXAGC_MIN     0x4
+#define BRXHP_INI      0x7
+#define BRXHP_TRLNA    0x70
+#define BRXHP_RSSI     0x700
+#define BRXHP_BBP1     0x7000
+#define BRXHP_BBP2     0x70000
+#define BRXHP_BBP3     0x700000
+#define BRSSI_H 0x7f0000
+#define BRSSI_GEN 0x7f000000
+#define BRXSETTLE_TRSW 0x7
+#define BRXSETTLE_LNA  0x38
+#define BRXSETTLE_RSSI 0x1c0
+#define BRXSETTLE_BBP 0xe00
+#define BRXSETTLE_RXHP 0x7000
+#define BRXSETTLE_ANTSW_RSSI   0x38000
+#define BRXSETTLE_ANTSW 0xc0000
+#define BRXPROCESS_TIME_DAGC   0x300000
+#define BRXSETTLE_HSSI 0x400000
+#define BRXPROCESS_TIME_BBPPW  0x800000
+#define BRXANTENNA_POWER_SHIFT 0x3000000
+#define BRSSI_TABLE_SELECT 0xc000000
+#define BRXHP_FINAL    0x7000000
+#define BRXHPSETTLE_BBP        0x7
+#define BRXHTSETTLE_HSSI       0x8
+#define BRXHTSETTLE_RXHP       0x70
+#define BRXHTSETTLE_BBPPW      0x80
+#define BRXHTSETTLE_IDLE       0x300
+#define BRXHTSETTLE_RESERVED 0x1c00
+#define BRXHT_RXHP_EN  0x8000
+#define BRXAGC_FREEZE_THRES    0x30000
+#define BRXAGC_TOGETHEREN      0x40000
+#define BRXHTAGC_MIN   0x80000
+#define BRXHTAGC_EN    0x100000
+#define BRXHTDAGC_EN   0x200000
+#define BRXHT_RXHP_BBP 0x1c00000
+#define BRXHT_RXHP_FINAL 0xe0000000
+#define BRXPW_RADIO_TH 0x3
+#define BRXPW_RADIO_EN 0x4
+#define BRXMF_HOLD     0x3800
+#define BRXPD_DELAY_TH1        0x38
+#define BRXPD_DELAY_TH2 0x1c0
+#define BRXPD_DC_COUNT_MAX     0x600
+#define BRXPD_DELAY_TH 0x8000
+#define BRXPROCESS_DELAY 0xf0000
+#define BRXSEARCHRANGE_GI2_EARLY       0x700000
+#define BRXFRAME_FUARD_COUNTER_L       0x3800000
+#define BRXSGI_GUARD_L 0xc000000
+#define BRXSGI_SEARCH_L        0x30000000
+#define BRXSGI_TH 0xc0000000
+#define BDFSCNT0 0xff
+#define BDFSCNT1 0xff00
+#define BDFSFLAG 0xf0000
+#define BMF_WEIGHT_SUM 0x300000
+#define BMINIDX_TH 0x7f000000
+#define BDAFORMAT      0x40000
+#define BTXCH_EMU_ENABLE       0x01000000
+#define BTRSW_ISOLATION_A 0x7f
+#define BTRSW_ISOLATION_B 0x7f00
+#define BTRSW_ISOLATION_C 0x7f0000
+#define BTRSW_ISOLATION_D 0x7f000000
+#define BEXT_LNA_GAIN 0x7c00
+
+#define BSTBC_EN       0x4
+#define BANTENNA_MAPPING       0x10
+#define BNSS   0x20
+#define BCFO_ANTSUM_ID 0x200
+#define BPHY_COUNTER_RESET     0x8000000
+#define BCFO_REPORT_GET        0x4000000
+#define BOFDM_CONTINUE_TX      0x10000000
+#define BOFDM_SINGLE_CARRIER   0x20000000
+#define BOFDM_SINGLE_TONE      0x40000000
+#define BHT_DETECT     0x100
+#define BCFOEN 0x10000
+#define BCFOVALUE 0xfff00000
+#define BSIGTONE_RE 0x3f
+#define BSIGTONE_IM 0x7f00
+#define BCOUNTER_CCA 0xffff
+#define BCOUNTER_PARITYFAIL 0xffff0000
+#define BCOUNTER_RATEILLEGAL 0xffff
+#define BCOUNTER_CRC8FAIL 0xffff0000
+#define BCOUNTER_MCSNOSUPPORT 0xffff
+#define BCOUNTER_FASTSYNC 0xffff
+#define BSHORTCFO 0xfff
+#define BSHORTCFOT_LENGTH      12
+#define BSHORTCFOF_LENGTH      11
+#define BLONGCFO 0x7ff
+#define BLONGCFOT_LENGTH       11
+#define BLONGCFOF_LENGTH       11
+#define BTAILCFO 0x1fff
+#define BTAILCFOT_LENGTH       13
+#define BTAILCFOF_LENGTH       12
+#define BNOISE_EN_PWDB 0xffff
+#define BCC_POWER_DB 0xffff0000
+#define BMOISE_PWDB 0xffff
+#define BPOWERMEAST_LENGTH     10
+#define BPOWERMEASF_LENGTH     3
+#define BRX_HT_BW      0x1
+#define BRXSC  0x6
+#define BRX_HT 0x8
+#define BNB_INTF_DET_ON        0x1
+#define BINTF_WIN_LEN_CFG      0x30
+#define BNB_INTF_TH_CFG 0x1c0
+#define BRFGAIN 0x3f
+#define BTABLESEL      0x40
+#define BTRSW  0x80
+#define BRXSNR_A 0xff
+#define BRXSNR_B 0xff00
+#define BRXSNR_C 0xff0000
+#define BRXSNR_D 0xff000000
+#define BSNR_EVMT_LENGTH       8
+#define BSNR_EVMF_LENGTH       1
+#define BCSI1ST 0xff
+#define BCSI2ND 0xff00
+#define BRXEVM1ST 0xff0000
+#define BRXEVM2ND 0xff000000
+#define BSIGEVM 0xff
+#define BPWDB 0xff00
+#define BSGIEN 0x10000
+
+#define BSFACTOR_QMA1 0xf
+#define BSFACTOR_QMA2 0xf0
+#define BSFACTOR_QMA3 0xf00
+#define BSFACTOR_QMA4 0xf000
+#define BSFACTOR_QMA5 0xf0000
+#define BSFACTOR_QMA6 0xf0000
+#define BSFACTOR_QMA7 0xf00000
+#define BSFACTOR_QMA8 0xf000000
+#define BSFACTOR_QMA9 0xf0000000
+#define BCSI_SCHEME    0x100000
+
+#define BNOISE_LVL_TOP_SET     0x3
+#define BCHSMOOTH      0x4
+#define BCHSMOOTH_CFG1 0x38
+#define BCHSMOOTH_CFG2 0x1c0
+#define BCHSMOOTH_CFG3 0xe00
+#define BCHSMOOTH_CFG4 0x7000
+#define BMRCMODE       0x800000
+#define BTHEVMCFG      0x7000000
+
+#define BLOOP_FIT_TYPE 0x1
+#define BUPD_CFO       0x40
+#define BUPD_CFO_OFFDATA       0x80
+#define BADV_UPD_CFO   0x100
+#define BADV_TIME_CTRL 0x800
+#define BUPD_CLKO      0x1000
+#define BFC    0x6000
+#define BTRACKING_MODE 0x8000
+#define BPHCMP_ENABLE  0x10000
+#define BUPD_CLKO_LTF  0x20000
+#define BCOM_CH_CFO    0x40000
+#define BCSI_ESTI_MODE 0x80000
+#define BADV_UPD_EQZ   0x100000
+#define BUCHCFG        0x7000000
+#define BUPDEQZ        0x8000000
+
+#define BRX_PESUDO_NOISE_ON    0x20000000
+#define BRX_PESUDO_NOISE_A 0xff
+#define BRX_PESUDO_NOISE_B 0xff00
+#define BRX_PESUDO_NOISE_C 0xff0000
+#define BRX_PESUDO_NOISE_D 0xff000000
+#define BRX_PESUDO_NOISESTATE_A 0xffff
+#define BRX_PESUDO_NOISESTATE_B 0xffff0000
+#define BRX_PESUDO_NOISESTATE_C 0xffff
+#define BRX_PESUDO_NOISESTATE_D 0xffff0000
+
+#define BZEBRA1_HSSIENABLE     0x8
+#define BZEBRA1_TRXCONTROL 0xc00
+#define BZEBRA1_TRXGAINSETTING 0x07f
+#define BZEBRA1_RXCOUNTER 0xc00
+#define BZEBRA1_TXCHANGEPUMP   0x38
+#define BZEBRA1_RXCHANGEPUMP   0x7
+#define BZEBRA1_CHANNEL_NUM 0xf80
+#define BZEBRA1_TXLPFBW        0x400
+#define BZEBRA1_RXLPFBW        0x600
+
+#define BRTL8256REG_MODE_CTRL1 0x100
+#define BRTL8256REG_MODE_CTRL0 0x40
+#define BRTL8256REG_TXLPFBW    0x18
+#define BRTL8256REG_RXLPFBW    0x600
+
+#define BRTL8258_TXLPFBW 0xc
+#define BRTL8258_RXLPFBW 0xc00
+#define BRTL8258_RSSILPFBW 0xc0
+
+#define BBYTE0 0x1
+#define BBYTE1 0x2
+#define BBYTE2 0x4
+#define BBYTE3 0x8
+#define BWORD0 0x3
+#define BWORD1 0xc
+#define BWORD 0xf
+
+#define MASKBYTE0 0xff
+#define MASKBYTE1 0xff00
+#define MASKBYTE2 0xff0000
+#define MASKBYTE3 0xff000000
+#define MASKHWORD 0xffff0000
+#define MASKLWORD 0x0000ffff
+#define MASKDWORD 0xffffffff
+#define MASK12BITS 0xfff
+#define MASKH4BITS 0xf0000000
+#define MASKOFDM_D 0xffc00000
+#define MASKCCK 0x3f3f3f3f
+
+#define MASK4BITS 0x0f
+#define MASK20BITS 0xfffff
+#define RFREG_OFFSET_MASK 0xfffff
+
+#define BMASKBYTE0 0xff
+#define BMASKBYTE1 0xff00
+#define BMASKBYTE2 0xff0000
+#define BMASKBYTE3 0xff000000
+#define BMASKHWORD 0xffff0000
+#define BMASKLWORD 0x0000ffff
+#define BMASKDWORD 0xffffffff
+#define BMASK12BITS 0xfff
+#define BMASKH4BITS 0xf0000000
+#define BMASKOFDM_D 0xffc00000
+#define BMASKCCK 0x3f3f3f3f
+
+#define BRFREGOFFSETMASK 0xfffff
+
+/* WOL bit information */
+#define WOL_REASON_PTK_UPDATE  BIT(0)
+#define WOL_REASON_GTK_UPDATE  BIT(1)
+#define WOL_REASON_DISASSOC    BIT(2)
+#define WOL_REASON_DEAUTH      BIT(3)
+#define WOL_REASON_FW_DISCONNECT       BIT(4)
+
+#endif
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../core.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "hw.h"
+#include "sw.h"
+#include "fw.h"
+#include "trx.h"
+#include "led.h"
+#include "../btcoexist/rtl_btc.h"
+#include "../halmac/rtl_halmac.h"
+#include "../phydm/rtl_phydm.h"
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+
+static void rtl8822be_init_aspm_vars(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+       /*close ASPM for AMD defaultly */
+       rtlpci->const_amdpci_aspm = 0;
+
+       /*
+        * ASPM PS mode.
+        * 0 - Disable ASPM,
+        * 1 - Enable ASPM without Clock Req,
+        * 2 - Enable ASPM with Clock Req,
+        * 3 - Alwyas Enable ASPM with Clock Req,
+        * 4 - Always Enable ASPM without Clock Req.
+        * set default to RTL8822BE:3 RTL8822B:2
+        *
+        */
+       rtlpci->const_pci_aspm = 3;
+
+       /*Setting for PCI-E device */
+       rtlpci->const_devicepci_aspm_setting = 0x03;
+
+       /*Setting for PCI-E bridge */
+       rtlpci->const_hostpci_aspm_setting = 0x02;
+
+       /*
+        * In Hw/Sw Radio Off situation.
+        * 0 - Default,
+        * 1 - From ASPM setting without low Mac Pwr,
+        * 2 - From ASPM setting with low Mac Pwr,
+        * 3 - Bus D3
+        * set default to RTL8822BE:0 RTL8192SE:2
+        */
+       rtlpci->const_hwsw_rfoff_d3 = 0;
+
+       /*
+        * This setting works for those device with
+        * backdoor ASPM setting such as EPHY setting.
+        * 0 - Not support ASPM,
+        * 1 - Support ASPM,
+        * 2 - According to chipset.
+        */
+       rtlpci->const_support_pciaspm = rtlpriv->cfg->mod_params->aspm_support;
+}
+
+int rtl8822be_init_sw_vars(struct ieee80211_hw *hw)
+{
+       int err = 0;
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       const char *fw_name;
+       struct rtl_phydm_params params;
+
+       rtl8822be_bt_reg_init(hw);
+       rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+       rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
+       rtlpriv->halmac.ops = rtl_halmac_get_ops_pointer();
+       rtlpriv->halmac.ops->halmac_init_adapter(rtlpriv);
+
+       /* should after halmac_init_adapter() */
+       rtl8822be_read_eeprom_info(hw, ¶ms);
+
+       /* need eeprom info */
+       rtlpriv->phydm.ops = rtl_phydm_get_ops_pointer();
+       rtlpriv->phydm.ops->phydm_init_priv(rtlpriv, ¶ms);
+
+       rtlpriv->dm.dm_initialgain_enable = 1;
+       rtlpriv->dm.dm_flag = 0;
+       rtlpriv->dm.disable_framebursting = 0;
+       /*rtlpriv->dm.thermalvalue = 0;*/
+       rtlpriv->dm.useramask = 1; /* turn on RA */
+       rtlpci->transmit_config = CFENDFORM | BIT(15);
+
+       rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G;
+       /*following 2 is for register 5G band, refer to _rtl_init_mac80211()*/
+       rtlpriv->rtlhal.bandset = BAND_ON_BOTH;
+       rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY;
+
+       rtlpci->receive_config = (RCR_APPFCS                    |
+                                 RCR_APP_MIC                   |
+                                 RCR_APP_ICV                   |
+                                 RCR_APP_PHYST_RXFF            |
+                                 RCR_VHT_DACK                  |
+                                 RCR_HTC_LOC_CTRL              |
+                                 /*RCR_AMF                     |*/
+                                 RCR_CBSSID_BCN                |
+                                 RCR_CBSSID_DATA               |
+                                 /*RCR_ACF                     |*/
+                                 /*RCR_ADF                     |*/
+                                 /*RCR_AICV                    |*/
+                                 /*RCR_ACRC32                  |*/
+                                 RCR_AB                        |
+                                 RCR_AM                        |
+                                 RCR_APM                       |
+                                 0);
+
+       rtlpci->irq_mask[0] = (u32)(IMR_PSTIMEOUT               |
+                                   /*IMR_TBDER                 |*/
+                                   /*IMR_TBDOK                 |*/
+                                   /*IMR_BCNDMAINT0            |*/
+                                   IMR_GTINT3                  |
+                                   IMR_HSISR_IND_ON_INT        |
+                                   IMR_C2HCMD                  |
+                                   IMR_HIGHDOK                 |
+                                   IMR_MGNTDOK                 |
+                                   IMR_BKDOK                   |
+                                   IMR_BEDOK                   |
+                                   IMR_VIDOK                   |
+                                   IMR_VODOK                   |
+                                   IMR_RDU                     |
+                                   IMR_ROK                     |
+                                   0);
+
+       rtlpci->irq_mask[1] = (u32)(IMR_RXFOVW | IMR_TXFOVW | 0);
+       rtlpci->irq_mask[3] = (u32)(BIT_SETH2CDOK_MASK | 0);
+
+       /* for LPS & IPS */
+       rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+       rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
+       rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+       rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+       if (rtlpriv->cfg->mod_params->disable_watchdog)
+               pr_info("watchdog disabled\n");
+       rtlpriv->psc.reg_fwctrl_lps = 2;
+       rtlpriv->psc.reg_max_lps_awakeintvl = 2;
+       /* for ASPM, you can close aspm through
+        * set const_support_pciaspm = 0
+        */
+       rtl8822be_init_aspm_vars(hw);
+
+       if (rtlpriv->psc.reg_fwctrl_lps == 1)
+               rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE;
+       else if (rtlpriv->psc.reg_fwctrl_lps == 2)
+               rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE;
+       else if (rtlpriv->psc.reg_fwctrl_lps == 3)
+               rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
+
+       /* for early mode */
+       rtlpriv->rtlhal.earlymode_enable = false;
+
+       /*low power */
+       rtlpriv->psc.low_power_enable = false;
+
+       /* for firmware buf */
+       rtlpriv->rtlhal.pfirmware = vzalloc(0x40000);
+       if (!rtlpriv->rtlhal.pfirmware) {
+               /*pr_err("Can't alloc buffer for fw\n");*/
+               return 1;
+       }
+
+       /* request fw */
+       fw_name = "rtlwifi/rtl8822befw.bin";
+
+       rtlpriv->max_fw_size = 0x40000;
+       pr_info("Using firmware %s\n", fw_name);
+       err = request_firmware_nowait(THIS_MODULE, 1, fw_name, rtlpriv->io.dev,
+                                     GFP_KERNEL, hw, rtl_fw_cb);
+       if (err) {
+               pr_err("Failed to request firmware!\n");
+               return 1;
+       }
+
+       /* init table of tx power by rate & limit */
+       rtl8822be_load_txpower_by_rate(hw);
+       rtl8822be_load_txpower_limit(hw);
+
+       return 0;
+}
+
+void rtl8822be_deinit_sw_vars(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       rtlpriv->halmac.ops->halmac_deinit_adapter(rtlpriv);
+       rtlpriv->phydm.ops->phydm_deinit_priv(rtlpriv);
+
+       if (rtlpriv->rtlhal.pfirmware) {
+               vfree(rtlpriv->rtlhal.pfirmware);
+               rtlpriv->rtlhal.pfirmware = NULL;
+       }
+}
+
+/* get bt coexist status */
+bool rtl8822be_get_btc_status(void)
+{
+       return true;
+}
+
+static void rtl8822be_phydm_watchdog(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u32 tmp;
+
+       tmp = rtl_read_dword(rtlpriv, 0xc00);
+       if (tmp & 0xFF000000) { /* Recover 0xC00: 0xF800000C --> 0x0000000C */
+               RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+                        "found regaddr_c00=%08X\n", tmp);
+               tmp &= ~0xFF000000;
+               rtl_write_dword(rtlpriv, 0xc00, tmp);
+               RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+                        "apply regaddr_c00=%08X\n", tmp);
+       }
+
+       rtlpriv->phydm.ops->phydm_watchdog(rtlpriv);
+}
+
+static struct rtl_hal_ops rtl8822be_hal_ops = {
+       .init_sw_vars = rtl8822be_init_sw_vars,
+       .deinit_sw_vars = rtl8822be_deinit_sw_vars,
+       .read_eeprom_info = rtl8822be_read_eeprom_info_dummy,
+       .interrupt_recognized = rtl8822be_interrupt_recognized,
+       .hw_init = rtl8822be_hw_init,
+       .hw_disable = rtl8822be_card_disable,
+       .hw_suspend = rtl8822be_suspend,
+       .hw_resume = rtl8822be_resume,
+       .enable_interrupt = rtl8822be_enable_interrupt,
+       .disable_interrupt = rtl8822be_disable_interrupt,
+       .set_network_type = rtl8822be_set_network_type,
+       .set_chk_bssid = rtl8822be_set_check_bssid,
+       .set_qos = rtl8822be_set_qos,
+       .set_bcn_reg = rtl8822be_set_beacon_related_registers,
+       .set_bcn_intv = rtl8822be_set_beacon_interval,
+       .update_interrupt_mask = rtl8822be_update_interrupt_mask,
+       .get_hw_reg = rtl8822be_get_hw_reg,
+       .set_hw_reg = rtl8822be_set_hw_reg,
+       .update_rate_tbl = rtl8822be_update_hal_rate_tbl,
+       .pre_fill_tx_bd_desc = rtl8822be_pre_fill_tx_bd_desc,
+       .rx_desc_buff_remained_cnt = rtl8822be_rx_desc_buff_remained_cnt,
+       .rx_check_dma_ok = rtl8822be_rx_check_dma_ok,
+       .fill_tx_desc = rtl8822be_tx_fill_desc,
+       .fill_tx_special_desc = rtl8822be_tx_fill_special_desc,
+       .query_rx_desc = rtl8822be_rx_query_desc,
+       .radio_onoff_checking = rtl8822be_gpio_radio_on_off_checking,
+       .switch_channel = rtl8822be_phy_sw_chnl,
+       .set_channel_access = rtl8822be_update_channel_access_setting,
+       .set_bw_mode = rtl8822be_phy_set_bw_mode,
+       .dm_watchdog = rtl8822be_phydm_watchdog,
+       .scan_operation_backup = rtl8822be_phy_scan_operation_backup,
+       .set_rf_power_state = rtl8822be_phy_set_rf_power_state,
+       .led_control = rtl8822be_led_control,
+       .set_desc = rtl8822be_set_desc,
+       .get_desc = rtl8822be_get_desc,
+       .is_tx_desc_closed = rtl8822be_is_tx_desc_closed,
+       .get_available_desc = rtl8822be_get_available_desc,
+       .tx_polling = rtl8822be_tx_polling,
+       .enable_hw_sec = rtl8822be_enable_hw_security_config,
+       .set_key = rtl8822be_set_key,
+       .init_sw_leds = rtl8822be_init_sw_leds,
+       .get_bbreg = rtl8822be_phy_query_bb_reg,
+       .set_bbreg = rtl8822be_phy_set_bb_reg,
+       .get_rfreg = rtl8822be_phy_query_rf_reg,
+       .set_rfreg = rtl8822be_phy_set_rf_reg,
+       .fill_h2c_cmd = rtl8822be_fill_h2c_cmd,
+       .set_default_port_id_cmd = rtl8822be_set_default_port_id_cmd,
+       .get_btc_status = rtl8822be_get_btc_status,
+       .rx_command_packet = rtl8822be_rx_command_packet,
+       .c2h_content_parsing = rtl8822be_c2h_content_parsing,
+       /* ops for halmac cb */
+       .halmac_cb_init_mac_register = rtl8822be_halmac_cb_init_mac_register,
+       .halmac_cb_init_bb_rf_register =
+               rtl8822be_halmac_cb_init_bb_rf_register,
+       .halmac_cb_write_data_rsvd_page =
+               rtl8822b_halmac_cb_write_data_rsvd_page,
+       .halmac_cb_write_data_h2c = rtl8822b_halmac_cb_write_data_h2c,
+       /* ops for phydm cb */
+       .get_txpower_index = rtl8822be_get_txpower_index,
+       .set_tx_power_index_by_rs = rtl8822be_phy_set_tx_power_index_by_rs,
+       .store_tx_power_by_rate = rtl8822be_store_tx_power_by_rate,
+       .phy_set_txpower_limit = rtl8822be_phy_set_txpower_limit,
+};
+
+static struct rtl_mod_params rtl8822be_mod_params = {
+       .sw_crypto = false,
+       .inactiveps = true,
+       .swctrl_lps = false,
+       .fwctrl_lps = true,
+       .msi_support = true,
+       .dma64 = false,
+       .aspm_support = 1,
+       .disable_watchdog = false,
+       .debug_level = 0,
+       .debug_mask = 0,
+};
+
+static struct rtl_hal_cfg rtl8822be_hal_cfg = {
+       .bar_id = 2,
+       .write_readback = false,
+       .name = "rtl8822be_pci",
+       .ops = &rtl8822be_hal_ops,
+       .mod_params = &rtl8822be_mod_params,
+       .spec_ver = RTL_SPEC_NEW_RATEID | RTL_SPEC_SUPPORT_VHT |
+                   RTL_SPEC_NEW_FW_C2H,
+       .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL_8822B,
+       .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN_8822B,
+       .maps[SYS_CLK] = REG_SYS_CLK_CTRL_8822B,
+       .maps[MAC_RCR_AM] = AM,
+       .maps[MAC_RCR_AB] = AB,
+       .maps[MAC_RCR_ACRC32] = ACRC32,
+       .maps[MAC_RCR_ACF] = ACF,
+       .maps[MAC_RCR_AAP] = AAP,
+       .maps[MAC_HIMR] = REG_HIMR0_8822B,
+       .maps[MAC_HIMRE] = REG_HIMR1_8822B,
+
+       .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS_8822B,
+
+       .maps[EFUSE_TEST] = REG_LDO_EFUSE_CTRL_8822B,
+       .maps[EFUSE_CTRL] = REG_EFUSE_CTRL_8822B,
+       .maps[EFUSE_CLK] = 0,
+       .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL_8822B,
+       .maps[EFUSE_PWC_EV12V] = PWC_EV12V,
+       .maps[EFUSE_FEN_ELDR] = FEN_ELDR,
+       .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN,
+       .maps[EFUSE_ANA8M] = ANA8M,
+       .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE,
+       .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
+       .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
+       .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES,
+
+       .maps[RWCAM] = REG_CAMCMD_8822B,
+       .maps[WCAMI] = REG_CAMWRITE_8822B,
+       .maps[RCAMO] = REG_CAMREAD_8822B,
+       .maps[CAMDBG] = REG_CAMDBG_8822B,
+       .maps[SECR] = REG_SECCFG_8822B,
+       .maps[SEC_CAM_NONE] = CAM_NONE,
+       .maps[SEC_CAM_WEP40] = CAM_WEP40,
+       .maps[SEC_CAM_TKIP] = CAM_TKIP,
+       .maps[SEC_CAM_AES] = CAM_AES,
+       .maps[SEC_CAM_WEP104] = CAM_WEP104,
+
+       .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
+       .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
+       .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
+       .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
+       .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
+       .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
+       /*      .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8,     */ /*need check*/
+       .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
+       .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
+       .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
+       .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
+       .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
+       .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
+       .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
+       /*      .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/
+       /*      .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/
+
+       .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
+       .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
+       .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0,
+       .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
+       .maps[RTL_IMR_RDU] = IMR_RDU,
+       .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
+       .maps[RTL_IMR_H2CDOK] = IMR_H2CDOK,
+       .maps[RTL_IMR_BDOK] = IMR_BCNDOK0,
+       .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK,
+       .maps[RTL_IMR_TBDER] = IMR_TBDER,
+       .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK,
+       .maps[RTL_IMR_TBDOK] = IMR_TBDOK,
+       .maps[RTL_IMR_BKDOK] = IMR_BKDOK,
+       .maps[RTL_IMR_BEDOK] = IMR_BEDOK,
+       .maps[RTL_IMR_VIDOK] = IMR_VIDOK,
+       .maps[RTL_IMR_VODOK] = IMR_VODOK,
+       .maps[RTL_IMR_ROK] = IMR_ROK,
+       .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER),
+
+       .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M,
+       .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M,
+       .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M,
+       .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M,
+       .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M,
+       .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M,
+       .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M,
+       .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M,
+       .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M,
+       .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M,
+       .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M,
+       .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M,
+
+       .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7,
+       .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15,
+
+       /*VHT hightest rate*/
+       .maps[RTL_RC_VHT_RATE_1SS_MCS7] = DESC_RATEVHT1SS_MCS7,
+       .maps[RTL_RC_VHT_RATE_1SS_MCS8] = DESC_RATEVHT1SS_MCS8,
+       .maps[RTL_RC_VHT_RATE_1SS_MCS9] = DESC_RATEVHT1SS_MCS9,
+       .maps[RTL_RC_VHT_RATE_2SS_MCS7] = DESC_RATEVHT2SS_MCS7,
+       .maps[RTL_RC_VHT_RATE_2SS_MCS8] = DESC_RATEVHT2SS_MCS8,
+       .maps[RTL_RC_VHT_RATE_2SS_MCS9] = DESC_RATEVHT2SS_MCS9,
+};
+
+static struct pci_device_id rtl8822be_pci_ids[] = {
+       {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB822, rtl8822be_hal_cfg)},
+       {},
+};
+
+MODULE_DEVICE_TABLE(pci, rtl8822be_pci_ids);
+
+MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
+MODULE_AUTHOR("Larry Finger    <Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8822BE 802.11n PCI wireless");
+MODULE_FIRMWARE("rtlwifi/rtl8822befw.bin");
+
+module_param_named(swenc, rtl8822be_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug_level, rtl8822be_mod_params.debug_level, int, 0644);
+module_param_named(debug_mask, rtl8822be_mod_params.debug_mask, ullong, 0644);
+module_param_named(ips, rtl8822be_mod_params.inactiveps, bool, 0444);
+module_param_named(swlps, rtl8822be_mod_params.swctrl_lps, bool, 0444);
+module_param_named(fwlps, rtl8822be_mod_params.fwctrl_lps, bool, 0444);
+module_param_named(msi, rtl8822be_mod_params.msi_support, bool, 0444);
+module_param_named(dma64, rtl8822be_mod_params.dma64, bool, 0444);
+module_param_named(aspm, rtl8822be_mod_params.aspm_support, int, 0444);
+module_param_named(disable_watchdog, rtl8822be_mod_params.disable_watchdog,
+                  bool, 0444);
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n");
+MODULE_PARM_DESC(dma64, "Set to 1 to use DMA 64 (default 0)\n");
+MODULE_PARM_DESC(aspm, "Set to 1 to enable ASPM (default 1)\n");
+MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)");
+MODULE_PARM_DESC(disable_watchdog,
+                "Set to 1 to disable the watchdog (default 0)\n");
+
+static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
+
+static struct pci_driver rtl8822be_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = rtl8822be_pci_ids,
+       .probe = rtl_pci_probe,
+       .remove = rtl_pci_disconnect,
+       .driver.pm = &rtlwifi_pm_ops,
+};
+
+module_pci_driver(rtl8822be_driver);
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8822B_SW_H__
+#define __RTL8822B_SW_H__
+
+int rtl8822be_init_sw_vars(struct ieee80211_hw *hw);
+void rtl8822be_deinit_sw_vars(struct ieee80211_hw *hw);
+bool rtl8822be_get_btc_status(void);
+#endif
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "../stats.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "trx.h"
+#include "led.h"
+#include "fw.h"
+
+#include <linux/vermagic.h>
+
+static u8 _rtl8822be_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
+{
+       switch (hw_queue) {
+       case BEACON_QUEUE:
+               return QSLT_BEACON;
+       case H2C_QUEUE:
+               return QSLT_CMD;
+       case MGNT_QUEUE:
+               return QSLT_MGNT;
+       case HIGH_QUEUE:
+               return QSLT_HIGH;
+       default:
+               return skb->priority;
+       }
+}
+
+static void _rtl8822be_query_rxphystatus(struct ieee80211_hw *hw, u8 *phystrpt,
+                                        struct ieee80211_hdr *hdr,
+                                        struct rtl_stats *pstatus)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       rtlpriv->phydm.ops->phydm_query_phy_status(rtlpriv, phystrpt, hdr,
+                                                  pstatus);
+
+       /* UI BSS List signal strength(in percentage),
+        * make it good looking, from 0~100.
+        */
+       pstatus->signalstrength =
+               (u8)(rtl_signal_scale_mapping(hw, pstatus->rx_pwdb_all));
+}
+
+static void _rtl8822be_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+                                                struct sk_buff *skb,
+                                                struct rtl_stats *pstatus,
+                                                u8 *p_phystrpt)
+{
+       struct ieee80211_hdr *hdr;
+       u8 *tmp_buf;
+
+       tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift +
+                 24;
+
+       hdr = (struct ieee80211_hdr *)tmp_buf;
+
+       /* query phy status */
+       _rtl8822be_query_rxphystatus(hw, p_phystrpt, hdr, pstatus);
+
+       /* packet statistics */
+       if (pstatus->packet_beacon && pstatus->packet_matchbssid)
+               rtl_priv(hw)->dm.dbginfo.num_qry_beacon_pkt++;
+
+       if (pstatus->packet_matchbssid &&
+           ieee80211_is_data_qos(hdr->frame_control) &&
+           !is_multicast_ether_addr(ieee80211_get_DA(hdr))) {
+               struct ieee80211_qos_hdr *hdr_qos =
+                       (struct ieee80211_qos_hdr *)tmp_buf;
+               u16 tid = le16_to_cpu(hdr_qos->qos_ctrl) & 0xf;
+
+               if (tid != 0 && tid != 3)
+                       rtl_priv(hw)->dm.dbginfo.num_non_be_pkt++;
+       }
+
+       /* signal statistics */
+       if (p_phystrpt)
+               rtl_process_phyinfo(hw, tmp_buf, pstatus);
+}
+
+static void _rtl8822be_insert_emcontent(struct rtl_tcb_desc *ptcb_desc,
+                                       u8 *virtualaddress)
+{
+       u32 dwtmp = 0;
+
+       memset(virtualaddress, 0, 8);
+
+       SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num);
+       if (ptcb_desc->empkt_num == 1) {
+               dwtmp = ptcb_desc->empkt_len[0];
+       } else {
+               dwtmp = ptcb_desc->empkt_len[0];
+               dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+               dwtmp += ptcb_desc->empkt_len[1];
+       }
+       SET_EARLYMODE_LEN0(virtualaddress, dwtmp);
+
+       if (ptcb_desc->empkt_num <= 3) {
+               dwtmp = ptcb_desc->empkt_len[2];
+       } else {
+               dwtmp = ptcb_desc->empkt_len[2];
+               dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+               dwtmp += ptcb_desc->empkt_len[3];
+       }
+       SET_EARLYMODE_LEN1(virtualaddress, dwtmp);
+       if (ptcb_desc->empkt_num <= 5) {
+               dwtmp = ptcb_desc->empkt_len[4];
+       } else {
+               dwtmp = ptcb_desc->empkt_len[4];
+               dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+               dwtmp += ptcb_desc->empkt_len[5];
+       }
+       SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF);
+       SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4);
+       if (ptcb_desc->empkt_num <= 7) {
+               dwtmp = ptcb_desc->empkt_len[6];
+       } else {
+               dwtmp = ptcb_desc->empkt_len[6];
+               dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+               dwtmp += ptcb_desc->empkt_len[7];
+       }
+       SET_EARLYMODE_LEN3(virtualaddress, dwtmp);
+       if (ptcb_desc->empkt_num <= 9) {
+               dwtmp = ptcb_desc->empkt_len[8];
+       } else {
+               dwtmp = ptcb_desc->empkt_len[8];
+               dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+               dwtmp += ptcb_desc->empkt_len[9];
+       }
+       SET_EARLYMODE_LEN4(virtualaddress, dwtmp);
+}
+
+static bool rtl8822be_get_rxdesc_is_ht(struct ieee80211_hw *hw, u8 *pdesc)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 rx_rate = 0;
+
+       rx_rate = GET_RX_DESC_RX_RATE(pdesc);
+
+       RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "rx_rate=0x%02x.\n", rx_rate);
+
+       if ((rx_rate >= DESC_RATEMCS0) && (rx_rate <= DESC_RATEMCS15))
+               return true;
+       else
+               return false;
+}
+
+static bool rtl8822be_get_rxdesc_is_vht(struct ieee80211_hw *hw, u8 *pdesc)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 rx_rate = 0;
+
+       rx_rate = GET_RX_DESC_RX_RATE(pdesc);
+
+       RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "rx_rate=0x%02x.\n", rx_rate);
+
+       if (rx_rate >= DESC_RATEVHT1SS_MCS0)
+               return true;
+       else
+               return false;
+}
+
+static u8 rtl8822be_get_rx_vht_nss(struct ieee80211_hw *hw, u8 *pdesc)
+{
+       u8 rx_rate = 0;
+       u8 vht_nss = 0;
+
+       rx_rate = GET_RX_DESC_RX_RATE(pdesc);
+
+       if ((rx_rate >= DESC_RATEVHT1SS_MCS0) &&
+           (rx_rate <= DESC_RATEVHT1SS_MCS9))
+               vht_nss = 1;
+       else if ((rx_rate >= DESC_RATEVHT2SS_MCS0) &&
+                (rx_rate <= DESC_RATEVHT2SS_MCS9))
+               vht_nss = 2;
+
+       return vht_nss;
+}
+
+bool rtl8822be_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *status,
+                            struct ieee80211_rx_status *rx_status, u8 *pdesc,
+                            struct sk_buff *skb)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 *p_phystrpt = NULL;
+       struct ieee80211_hdr *hdr;
+
+       u32 phystatus = GET_RX_DESC_PHYST(pdesc);
+
+       if (GET_RX_DESC_C2H(pdesc) == 0)
+               status->packet_report_type = NORMAL_RX;
+       else
+               status->packet_report_type = C2H_PACKET;
+
+       status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc);
+       status->rx_drvinfo_size =
+               (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * RX_DRV_INFO_SIZE_UNIT;
+       status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03);
+       status->icv = (u16)GET_RX_DESC_ICV_ERR(pdesc);
+       status->crc = (u16)GET_RX_DESC_CRC32(pdesc);
+       status->hwerror = (status->crc | status->icv);
+       status->decrypted = !GET_RX_DESC_SWDEC(pdesc);
+       status->rate = (u8)GET_RX_DESC_RX_RATE(pdesc);
+       status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1);
+       status->isfirst_ampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1);
+       status->timestamp_low = GET_RX_DESC_TSFL(pdesc);
+       status->is_ht = rtl8822be_get_rxdesc_is_ht(hw, pdesc);
+       status->is_vht = rtl8822be_get_rxdesc_is_vht(hw, pdesc);
+       status->vht_nss = rtl8822be_get_rx_vht_nss(hw, pdesc);
+       status->is_cck = RX_HAL_IS_CCK_RATE(status->rate);
+
+       status->macid = GET_RX_DESC_MACID(pdesc);
+       if (GET_RX_DESC_PATTERN_MATCH(pdesc))
+               status->wake_match = BIT(2);
+       else if (GET_RX_DESC_MAGIC_WAKE(pdesc))
+               status->wake_match = BIT(1);
+       else if (GET_RX_DESC_UNICAST_WAKE(pdesc))
+               status->wake_match = BIT(0);
+       else
+               status->wake_match = 0;
+       if (status->wake_match)
+               RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD,
+                        "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n",
+                        status->wake_match);
+       rx_status->freq = hw->conf.chandef.chan->center_freq;
+       rx_status->band = hw->conf.chandef.chan->band;
+
+       if (phystatus)
+               p_phystrpt = (skb->data + status->rx_bufshift + 24);
+
+       hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size +
+                                      status->rx_bufshift + 24);
+
+       if (status->crc)
+               rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+
+       if (status->is_ht)
+               rx_status->encoding = RX_ENC_HT;
+       if (status->is_vht)
+               rx_status->encoding = RX_ENC_VHT;
+
+       rx_status->nss = status->vht_nss;
+
+       rx_status->flag |= RX_FLAG_MACTIME_START;
+
+       /* hw will set status->decrypted true, if it finds the
+        * frame is open data frame or mgmt frame.
+        */
+       /* So hw will not decryption robust management frame
+        * for IEEE80211w but still set status->decrypted
+        * true, so here we should set it back to undecrypted
+        * for IEEE80211w frame, and mac80211 sw will help
+        * to decrypt it
+        */
+       if (status->decrypted) {
+               if (!hdr) {
+                       WARN_ON_ONCE(true);
+                       pr_err("decrypted is true but hdr NULL, from skb %p\n",
+                              rtl_get_hdr(skb));
+                       return false;
+               }
+
+               if ((!_ieee80211_is_robust_mgmt_frame(hdr)) &&
+                   (ieee80211_has_protected(hdr->frame_control)))
+                       rx_status->flag |= RX_FLAG_DECRYPTED;
+               else
+                       rx_status->flag &= ~RX_FLAG_DECRYPTED;
+       }
+
+       /* rate_idx: index of data rate into band's
+        * supported rates or MCS index if HT rates
+        * are use (RX_FLAG_HT)
+        */
+       /* Notice: this is diff with windows define */
+       rx_status->rate_idx = rtlwifi_rate_mapping(
+               hw, status->is_ht, status->is_vht, status->rate);
+
+       rx_status->mactime = status->timestamp_low;
+
+       _rtl8822be_translate_rx_signal_stuff(hw, skb, status, p_phystrpt);
+
+       /* below info. are filled by _rtl8822be_translate_rx_signal_stuff() */
+       if (!p_phystrpt)
+               goto label_no_physt;
+
+       rx_status->signal = status->recvsignalpower;
+
+       if (status->rx_packet_bw == HT_CHANNEL_WIDTH_20_40)
+               rx_status->bw = RATE_INFO_BW_40;
+       else if (status->rx_packet_bw == HT_CHANNEL_WIDTH_80)
+               rx_status->bw = RATE_INFO_BW_80;
+
+label_no_physt:
+
+       return true;
+}
+
+void rtl8822be_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc,
+                              u8 queue_index)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 first_seg;
+       u8 last_seg;
+       u16 total_len;
+       u16 read_cnt = 0;
+
+       if (!header_desc)
+               return;
+
+       do {
+               total_len = (u16)GET_RX_BUFFER_DESC_TOTAL_LENGTH(header_desc);
+               first_seg = (u8)GET_RX_BUFFER_DESC_FS(header_desc);
+               last_seg = (u8)GET_RX_BUFFER_DESC_LS(header_desc);
+
+               if (read_cnt++ > 20) {
+                       RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG,
+                                "RX chk DMA over %d times\n", read_cnt);
+                       break;
+               }
+
+       } while (total_len == 0 && first_seg == 0 && last_seg == 0);
+}
+
+u16 rtl8822be_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, u8 queue_index)
+{
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u16 desc_idx_hw = 0, desc_idx_host = 0, remind_cnt = 0;
+       u32 tmp_4byte = 0;
+
+       u32 rw_mask = 0x1ff;
+
+       tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_RXBD_IDX_8822B);
+       desc_idx_hw = (u16)((tmp_4byte >> 16) & rw_mask);
+       desc_idx_host = (u16)(tmp_4byte & rw_mask);
+
+       /* may be no data, donot rx */
+       if (desc_idx_hw == desc_idx_host)
+               return 0;
+
+       remind_cnt =
+               (desc_idx_hw > desc_idx_host) ?
+                       (desc_idx_hw - desc_idx_host) :
+                       (RX_DESC_NUM_8822BE - (desc_idx_host - desc_idx_hw));
+
+       rtlpci->rx_ring[queue_index].next_rx_rp = desc_idx_host;
+
+       return remind_cnt;
+}
+
+static u16 get_desc_address_from_queue_index(u16 queue_index)
+{
+       /*
+        * Note: Access these registers will take a lot of cost.
+        */
+       u16 desc_address = REG_BEQ_TXBD_IDX_8822B;
+
+       switch (queue_index) {
+       case BK_QUEUE:
+               desc_address = REG_BKQ_TXBD_IDX_8822B;
+               break;
+       case BE_QUEUE:
+               desc_address = REG_BEQ_TXBD_IDX_8822B;
+               break;
+       case VI_QUEUE:
+               desc_address = REG_VIQ_TXBD_IDX_8822B;
+               break;
+       case VO_QUEUE:
+               desc_address = REG_VOQ_TXBD_IDX_8822B;
+               break;
+       case BEACON_QUEUE:
+               desc_address = REG_BEQ_TXBD_IDX_8822B;
+               break;
+       case H2C_QUEUE:
+               desc_address = REG_H2CQ_TXBD_IDX_8822B;
+               break;
+       case MGNT_QUEUE:
+               desc_address = REG_MGQ_TXBD_IDX_8822B;
+               break;
+       case HIGH_QUEUE:
+               desc_address = REG_HI0Q_TXBD_IDX_8822B;
+               break;
+       case HCCA_QUEUE:
+               desc_address = REG_BEQ_TXBD_IDX_8822B;
+               break;
+       default:
+               break;
+       }
+       return desc_address;
+}
+
+/*free  desc that can be used */
+u16 rtl8822be_get_available_desc(struct ieee80211_hw *hw, u8 q_idx)
+{
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[q_idx];
+
+       return calc_fifo_space(ring->cur_tx_rp, ring->cur_tx_wp,
+                              TX_DESC_NUM_8822B);
+}
+
+void rtl8822be_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, u8 *tx_bd_desc,
+                                  u8 *desc, u8 queue_index,
+                                  struct sk_buff *skb, dma_addr_t data_addr)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       u32 pkt_len = skb->len;
+       u16 desc_size = 48; /*tx desc size*/
+       u32 psblen = 0;
+       u32 total_packet_size = 0;
+       u16 current_bd_desc;
+       u8 i = 0;
+       /*u16 real_desc_size = 0x28;*/
+       u16 append_early_mode_size = 0;
+       u8 segmentnum = 1 << (RTL8822BE_SEG_NUM + 1);
+       dma_addr_t desc_dma_addr;
+       bool dma64 = rtlpriv->cfg->mod_params->dma64;
+
+       current_bd_desc = rtlpci->tx_ring[queue_index].cur_tx_wp;
+
+       total_packet_size = desc_size + pkt_len;
+
+       if (rtlpriv->rtlhal.earlymode_enable) {
+               if (queue_index < BEACON_QUEUE) {
+                       append_early_mode_size = 8;
+                       total_packet_size += append_early_mode_size;
+               }
+       }
+
+       /* page number (round up) */
+       psblen = (total_packet_size - 1) / 128 + 1;
+
+       /* tx desc addr */
+       desc_dma_addr = rtlpci->tx_ring[queue_index].dma +
+                       (current_bd_desc * TX_DESC_SIZE);
+
+       /* Reset */
+       SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, 0);
+       SET_TX_BUFF_DESC_PSB(tx_bd_desc, 0);
+       SET_TX_BUFF_DESC_OWN(tx_bd_desc, 0);
+
+       for (i = 1; i < segmentnum; i++) {
+               SET_TXBUFFER_DESC_LEN_WITH_OFFSET(tx_bd_desc, i, 0);
+               SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(tx_bd_desc, i, 0);
+               SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(tx_bd_desc, i, 0);
+               SET_TXBUFFER_DESC_ADD_HIGH_WITH_OFFSET(tx_bd_desc, i, 0, dma64);
+       }
+
+       /* Clear all status */
+       CLEAR_PCI_TX_DESC_CONTENT(desc, TX_DESC_SIZE);
+
+       if (rtlpriv->rtlhal.earlymode_enable) {
+               if (queue_index < BEACON_QUEUE)
+                       SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, desc_size + 8);
+               else
+                       SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, desc_size);
+       } else {
+               SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, desc_size);
+       }
+       SET_TX_BUFF_DESC_PSB(tx_bd_desc, psblen);
+       SET_TX_BUFF_DESC_ADDR_LOW_0(tx_bd_desc, desc_dma_addr);
+       SET_TX_BUFF_DESC_ADDR_HIGH_0(tx_bd_desc, ((u64)desc_dma_addr >> 32),
+                                    dma64);
+
+       SET_TXBUFFER_DESC_LEN_WITH_OFFSET(tx_bd_desc, 1, pkt_len);
+       SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(tx_bd_desc, 1, 0);
+       SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(tx_bd_desc, 1, data_addr);
+       SET_TXBUFFER_DESC_ADD_HIGH_WITH_OFFSET(tx_bd_desc, 1,
+                                              ((u64)data_addr >> 32), dma64);
+
+       SET_TX_DESC_TXPKTSIZE(desc, (u16)(pkt_len));
+}
+
+static u8 rtl8822be_bw_mapping(struct ieee80211_hw *hw,
+                              struct rtl_tcb_desc *ptcb_desc)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 bw_setting_of_desc = 0;
+
+       RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                "%s, current_chan_bw %d, packet_bw %d\n", __func__,
+                rtlphy->current_chan_bw, ptcb_desc->packet_bw);
+
+       if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) {
+               if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_80)
+                       bw_setting_of_desc = 2;
+               else if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40)
+                       bw_setting_of_desc = 1;
+               else
+                       bw_setting_of_desc = 0;
+       } else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+               if ((ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) ||
+                   (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_80))
+                       bw_setting_of_desc = 1;
+               else
+                       bw_setting_of_desc = 0;
+       } else {
+               bw_setting_of_desc = 0;
+       }
+
+       return bw_setting_of_desc;
+}
+
+static u8 rtl8822be_sc_mapping(struct ieee80211_hw *hw,
+                              struct rtl_tcb_desc *ptcb_desc)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       struct rtl_mac *mac = rtl_mac(rtlpriv);
+       u8 sc_setting_of_desc = 0;
+
+       if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) {
+               if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_80) {
+                       sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE;
+               } else if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) {
+                       if (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER)
+                               sc_setting_of_desc =
+                                       VHT_DATA_SC_40_LOWER_OF_80MHZ;
+                       else if (mac->cur_80_prime_sc ==
+                                HAL_PRIME_CHNL_OFFSET_UPPER)
+                               sc_setting_of_desc =
+                                       VHT_DATA_SC_40_UPPER_OF_80MHZ;
+                       else
+                               RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD,
+                                        "%s: Not Correct Primary40MHz Setting\n",
+                                        __func__);
+               } else {
+                       if ((mac->cur_40_prime_sc ==
+                            HAL_PRIME_CHNL_OFFSET_LOWER) &&
+                           (mac->cur_80_prime_sc ==
+                            HAL_PRIME_CHNL_OFFSET_LOWER))
+                               sc_setting_of_desc =
+                                       VHT_DATA_SC_20_LOWEST_OF_80MHZ;
+                       else if ((mac->cur_40_prime_sc ==
+                                 HAL_PRIME_CHNL_OFFSET_UPPER) &&
+                                (mac->cur_80_prime_sc ==
+                                 HAL_PRIME_CHNL_OFFSET_LOWER))
+                               sc_setting_of_desc =
+                                       VHT_DATA_SC_20_LOWER_OF_80MHZ;
+                       else if ((mac->cur_40_prime_sc ==
+                                 HAL_PRIME_CHNL_OFFSET_LOWER) &&
+                                (mac->cur_80_prime_sc ==
+                                 HAL_PRIME_CHNL_OFFSET_UPPER))
+                               sc_setting_of_desc =
+                                       VHT_DATA_SC_20_UPPER_OF_80MHZ;
+                       else if ((mac->cur_40_prime_sc ==
+                                 HAL_PRIME_CHNL_OFFSET_UPPER) &&
+                                (mac->cur_80_prime_sc ==
+                                 HAL_PRIME_CHNL_OFFSET_UPPER))
+                               sc_setting_of_desc =
+                                       VHT_DATA_SC_20_UPPERST_OF_80MHZ;
+                       else
+                               RT_TRACE(
+                                       rtlpriv, COMP_SEND, DBG_LOUD,
+                                       "rtl8822be_sc_mapping: Not Correct Primary40MHz Setting\n");
+               }
+       } else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+               if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) {
+                       sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE;
+               } else if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20) {
+                       if (mac->cur_40_prime_sc ==
+                           HAL_PRIME_CHNL_OFFSET_UPPER) {
+                               sc_setting_of_desc =
+                                       VHT_DATA_SC_20_UPPER_OF_80MHZ;
+                       } else if (mac->cur_40_prime_sc ==
+                                  HAL_PRIME_CHNL_OFFSET_LOWER) {
+                               sc_setting_of_desc =
+                                       VHT_DATA_SC_20_LOWER_OF_80MHZ;
+                       } else {
+                               sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE;
+                       }
+               }
+       } else {
+               sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE;
+       }
+
+       return sc_setting_of_desc;
+}
+
+void rtl8822be_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+                           u8 *pdesc_tx, u8 *pbd_desc_tx,
+                           struct ieee80211_tx_info *info,
+                           struct ieee80211_sta *sta, struct sk_buff *skb,
+                           u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+       struct rtl_phy *rtlphy = &rtlpriv->phy;
+       u8 *pdesc = (u8 *)pdesc_tx;
+       u16 seq_number;
+       __le16 fc = hdr->frame_control;
+       u8 fw_qsel = _rtl8822be_map_hwqueue_to_fwqueue(skb, hw_queue);
+       bool firstseg =
+               ((hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
+       bool lastseg = ((hdr->frame_control &
+                        cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
+       dma_addr_t mapping;
+       u8 short_gi = 0;
+
+       seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+       rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
+       /* reserve 8 byte for AMPDU early mode */
+       if (rtlhal->earlymode_enable) {
+               skb_push(skb, EM_HDR_LEN);
+               memset(skb->data, 0, EM_HDR_LEN);
+       }
+       mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
+                                PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "DMA mapping error");
+               return;
+       }
+
+       if (pbd_desc_tx)
+               rtl8822be_pre_fill_tx_bd_desc(hw, pbd_desc_tx, pdesc, hw_queue,
+                                             skb, mapping);
+
+       if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
+               firstseg = true;
+               lastseg = true;
+       }
+       if (firstseg) {
+               if (rtlhal->earlymode_enable) {
+                       SET_TX_DESC_PKT_OFFSET(pdesc, 1);
+                       SET_TX_DESC_OFFSET(pdesc,
+                                          USB_HWDESC_HEADER_LEN + EM_HDR_LEN);
+                       if (ptcb_desc->empkt_num) {
+                               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                                        "Insert 8 byte.pTcb->EMPktNum:%d\n",
+                                        ptcb_desc->empkt_num);
+                               _rtl8822be_insert_emcontent(ptcb_desc,
+                                                           (u8 *)(skb->data));
+                       }
+               } else {
+                       SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+               }
+
+               /* tx report */
+               rtl_get_tx_report(ptcb_desc, pdesc, hw);
+
+               if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G &&
+                   ptcb_desc->hw_rate < DESC_RATE6M) {
+                       RT_TRACE(rtlpriv, COMP_SEND, DBG_WARNING,
+                                "hw_rate=0x%X is invalid in 5G\n",
+                                ptcb_desc->hw_rate);
+                       ptcb_desc->hw_rate = DESC_RATE6M;
+               }
+               SET_TX_DESC_DATARATE(pdesc, ptcb_desc->hw_rate);
+
+               if (ptcb_desc->hw_rate > DESC_RATEMCS0)
+                       short_gi = (ptcb_desc->use_shortgi) ? 1 : 0;
+               else
+                       short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0;
+
+               if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+                       SET_TX_DESC_AGG_EN(pdesc, 1);
+                       SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x1F);
+               }
+               SET_TX_DESC_SW_SEQ(pdesc, seq_number);
+               SET_TX_DESC_RTSEN(pdesc, ((ptcb_desc->rts_enable &&
+                                          !ptcb_desc->cts_enable) ?
+                                                 1 :
+                                                 0));
+               SET_TX_DESC_HW_RTS_EN(pdesc, 0);
+               SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0));
+
+               SET_TX_DESC_RTSRATE(pdesc, ptcb_desc->rts_rate);
+               SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc);
+               SET_TX_DESC_RTS_SHORT(
+                       pdesc,
+                       ((ptcb_desc->rts_rate <= DESC_RATE54M) ?
+                                (ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
+                                (ptcb_desc->rts_use_shortgi ? 1 : 0)));
+
+               if (ptcb_desc->tx_enable_sw_calc_duration)
+                       SET_TX_DESC_NAVUSEHDR(pdesc, 1);
+
+               SET_TX_DESC_DATA_BW(pdesc, rtl8822be_bw_mapping(hw, ptcb_desc));
+               SET_TX_DESC_DATA_SC(pdesc, rtl8822be_sc_mapping(hw, ptcb_desc));
+
+               if (sta) {
+                       u8 ampdu_density = sta->ht_cap.ampdu_density;
+
+                       SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
+               }
+               if (info->control.hw_key) {
+                       struct ieee80211_key_conf *key = info->control.hw_key;
+
+                       switch (key->cipher) {
+                       case WLAN_CIPHER_SUITE_WEP40:
+                       case WLAN_CIPHER_SUITE_WEP104:
+                       case WLAN_CIPHER_SUITE_TKIP:
+                               SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
+                               break;
+                       case WLAN_CIPHER_SUITE_CCMP:
+                               SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
+                               break;
+                       default:
+                               SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
+                               break;
+                       }
+               }
+
+               SET_TX_DESC_QSEL(pdesc, fw_qsel);
+
+               if (rtlphy->current_channel > 14) {
+                       /* OFDM 6M */
+                       SET_TX_DESC_DATA_RTY_LOWEST_RATE(pdesc, 4);
+                       SET_TX_DESC_RTS_RTY_LOWEST_RATE(pdesc, 4);
+               } else {
+                       /* CCK 1M */
+                       SET_TX_DESC_DATA_RTY_LOWEST_RATE(pdesc, 0);
+                       SET_TX_DESC_RTS_RTY_LOWEST_RATE(pdesc, 0);
+               }
+               SET_TX_DESC_DISDATAFB(pdesc,
+                                     ptcb_desc->disable_ratefallback ? 1 : 0);
+               SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0);
+
+               /*SET_TX_DESC_PWR_STATUS(pdesc, pwr_status);*/
+               /* Set TxRate and RTSRate in TxDesc  */
+               /* This prevent Tx initial rate of new-coming packets */
+               /* from being overwritten by retried  packet rate.*/
+               if (!ptcb_desc->use_driver_rate) {
+                       /*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */
+                       /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */
+               }
+               if (ieee80211_is_data_qos(fc)) {
+                       if (mac->rdg_en) {
+                               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                                        "Enable RDG function.\n");
+                               SET_TX_DESC_RDG_EN(pdesc, 1);
+                               SET_TX_DESC_HTC(pdesc, 1);
+                       }
+               }
+
+               SET_TX_DESC_PORT_ID(pdesc, 0);
+               SET_TX_DESC_MULTIPLE_PORT(pdesc, 0);
+       }
+
+       SET_TX_DESC_LS(pdesc, (lastseg ? 1 : 0));
+       if (rtlpriv->dm.useramask) {
+               SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index);
+               SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id);
+       } else {
+               SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index);
+               SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index);
+       }
+
+       SET_TX_DESC_MOREFRAG(pdesc, (lastseg ? 0 : 1));
+       if (ptcb_desc->multicast || ptcb_desc->broadcast) {
+               SET_TX_DESC_BMC(pdesc, 1);
+               /* BMC must be not AGG */
+               SET_TX_DESC_AGG_EN(pdesc, 0);
+       }
+       RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
+
+       /* debug purpose: used to check tx desc is correct or not */
+       /*rtlpriv->halmac.ops->halmac_chk_txdesc(rtlpriv, pdesc,
+        *                      skb->len + USB_HWDESC_HEADER_LEN);
+        */
+}
+
+void rtl8822be_tx_fill_special_desc(struct ieee80211_hw *hw, u8 *pdesc,
+                                   u8 *pbd_desc, struct sk_buff *skb,
+                                   u8 hw_queue)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       u8 fw_queue;
+       u8 txdesc_len = 48;
+
+       dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
+                                           PCI_DMA_TODEVICE);
+
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "DMA mapping error");
+               return;
+       }
+
+       rtl8822be_pre_fill_tx_bd_desc(hw, pbd_desc, pdesc, hw_queue, skb,
+                                     mapping);
+
+       /* it should be BEACON_QUEUE or H2C_QUEUE,
+        * so skb=NULL is safe to assert
+        */
+       fw_queue = _rtl8822be_map_hwqueue_to_fwqueue(NULL, hw_queue);
+
+       CLEAR_PCI_TX_DESC_CONTENT(pdesc, txdesc_len);
+
+       /* common part for BEACON and H2C */
+       SET_TX_DESC_TXPKTSIZE((u8 *)pdesc, (u16)(skb->len));
+
+       SET_TX_DESC_QSEL(pdesc, fw_queue);
+
+       if (hw_queue == H2C_QUEUE) {
+               /* fill H2C */
+               SET_TX_DESC_OFFSET(pdesc, 0);
+
+       } else {
+               /* fill beacon */
+               SET_TX_DESC_OFFSET(pdesc, txdesc_len);
+
+               SET_TX_DESC_DATARATE(pdesc, DESC_RATE1M);
+
+               SET_TX_DESC_SW_SEQ(pdesc, 0);
+
+               SET_TX_DESC_RATE_ID(pdesc, 7);
+               SET_TX_DESC_MACID(pdesc, 0);
+
+               SET_TX_DESC_LS(pdesc, 1);
+
+               SET_TX_DESC_OFFSET(pdesc, 48);
+
+               SET_TX_DESC_USE_RATE(pdesc, 1);
+       }
+
+       RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content\n",
+                     pdesc, txdesc_len);
+}
+
+void rtl8822be_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
+                       u8 desc_name, u8 *val)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 q_idx = *val;
+       bool dma64 = rtlpriv->cfg->mod_params->dma64;
+
+       if (istx) {
+               switch (desc_name) {
+               case HW_DESC_OWN: {
+                       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+                       struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[q_idx];
+                       u16 max_tx_desc = ring->entries;
+
+                       if (q_idx == BEACON_QUEUE) {
+                               /* in case of beacon, pdesc is BD desc. */
+                               u8 *pbd_desc = pdesc;
+
+                               ring->cur_tx_wp = 0;
+                               ring->cur_tx_rp = 0;
+                               SET_TX_BUFF_DESC_OWN(pbd_desc, 1);
+                               return;
+                       }
+
+                       /* make sure tx desc is available by caller */
+                       ring->cur_tx_wp = ((ring->cur_tx_wp + 1) % max_tx_desc);
+
+                       rtl_write_word(
+                               rtlpriv,
+                               get_desc_address_from_queue_index(
+                                       q_idx),
+                               ring->cur_tx_wp);
+               } break;
+               }
+       } else {
+               switch (desc_name) {
+               case HW_DESC_RX_PREPARE:
+                       SET_RX_BUFFER_DESC_LS(pdesc, 0);
+                       SET_RX_BUFFER_DESC_FS(pdesc, 0);
+                       SET_RX_BUFFER_DESC_TOTAL_LENGTH(pdesc, 0);
+
+                       SET_RX_BUFFER_DESC_DATA_LENGTH(
+                               pdesc, MAX_RECEIVE_BUFFER_SIZE + RX_DESC_SIZE);
+
+                       SET_RX_BUFFER_PHYSICAL_LOW(
+                               pdesc, (*(dma_addr_t *)val) & DMA_BIT_MASK(32));
+                       SET_RX_BUFFER_PHYSICAL_HIGH(
+                               pdesc, ((u64)(*(dma_addr_t *)val) >> 32),
+                               dma64);
+                       break;
+               default:
+                       WARN_ONCE(true, "ERR rxdesc :%d not process\n",
+                                 desc_name);
+                       break;
+               }
+       }
+}
+
+u64 rtl8822be_get_desc(struct ieee80211_hw *hw,
+                      u8 *pdesc, bool istx, u8 desc_name)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u64 ret = 0;
+       u8 *pbd_desc = pdesc;
+       bool dma64 = rtlpriv->cfg->mod_params->dma64;
+
+       if (istx) {
+               switch (desc_name) {
+               case HW_DESC_TXBUFF_ADDR:
+                       ret = GET_TXBUFFER_DESC_ADDR_LOW(pbd_desc, 1);
+                       ret |= (u64)GET_TXBUFFER_DESC_ADDR_HIGH(pbd_desc, 1,
+                                                               dma64) << 32;
+                       break;
+               default:
+                       WARN_ONCE(true, "ERR txdesc :%d not process\n",
+                                 desc_name);
+                       break;
+               }
+       } else {
+               switch (desc_name) {
+               case HW_DESC_RXPKT_LEN:
+                       ret = GET_RX_DESC_PKT_LEN(pdesc);
+                       break;
+               default:
+                       WARN_ONCE(true, "ERR rxdesc :%d not process\n",
+                                 desc_name);
+                       break;
+               }
+       }
+       return ret;
+}
+
+bool rtl8822be_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue,
+                                u16 index)
+{
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       bool ret = false;
+       struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
+       u16 cur_tx_rp, cur_tx_wp;
+       u16 tmp16;
+
+       /*
+        * design rule:
+        *     idx <= cur_tx_rp <= hw_rp <= cur_tx_wp = hw_wp
+        */
+
+       if (index == ring->cur_tx_rp) {
+               /* update only if sw_rp reach hw_rp */
+               tmp16 = rtl_read_word(
+                           rtlpriv,
+                           get_desc_address_from_queue_index(hw_queue) + 2);
+
+               cur_tx_rp = tmp16 & 0x01ff;
+               cur_tx_wp = ring->cur_tx_wp;
+
+               /* don't need to update ring->cur_tx_wp */
+               ring->cur_tx_rp = cur_tx_rp;
+       }
+
+       if (index == ring->cur_tx_rp)
+               ret = false;    /* no more */
+       else
+               ret = true;     /* more */
+
+       if (hw_queue == BEACON_QUEUE)
+               ret = true;
+
+       if (rtlpriv->rtlhal.driver_is_goingto_unload ||
+           rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS)
+               ret = true;
+
+       return ret;
+}
+
+void rtl8822be_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       if (hw_queue == BEACON_QUEUE) {
+               /* kick start */
+               rtl_write_byte(
+                       rtlpriv, REG_RX_RXBD_NUM_8822B + 1,
+                       rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1) |
+                               BIT(4));
+       }
+}
+
+u32 rtl8822be_rx_command_packet(struct ieee80211_hw *hw,
+                               const struct rtl_stats *status,
+                               struct sk_buff *skb)
+{
+       u32 result = 0;
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       switch (status->packet_report_type) {
+       case NORMAL_RX:
+               result = 0;
+               break;
+       case C2H_PACKET:
+               rtl8822be_c2h_packet_handler(hw, skb->data, (u8)skb->len);
+               result = 1;
+               break;
+       default:
+               RT_TRACE(rtlpriv, COMP_RECV, DBG_TRACE,
+                        "Unknown packet type %d\n",
+                        status->packet_report_type);
+               break;
+       }
+
+       return result;
+}
 
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright(c) 2016  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8822B_TRX_H__
+#define __RTL8822B_TRX_H__
+
+#include "../halmac/halmac_tx_desc_nic.h"
+#include "../halmac/halmac_rx_desc_nic.h"
+
+#define TX_DESC_SIZE   64
+
+#define RX_DRV_INFO_SIZE_UNIT  8
+
+#define TX_DESC_NEXT_DESC_OFFSET       48
+#define USB_HWDESC_HEADER_LEN  48
+
+#define RX_DESC_SIZE   24
+#define MAX_RECEIVE_BUFFER_SIZE        8192
+
+#define SET_EARLYMODE_PKTNUM(__paddr, __val)                                   \
+       SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __val)
+#define SET_EARLYMODE_LEN0(__paddr, __val)                                     \
+       SET_BITS_TO_LE_4BYTE(__paddr, 4, 15, __val)
+#define SET_EARLYMODE_LEN1(__paddr, __val)                                     \
+       SET_BITS_TO_LE_4BYTE(__paddr, 16, 2, __val)
+#define SET_EARLYMODE_LEN1_1(__paddr, __val)                                   \
+       SET_BITS_TO_LE_4BYTE(__paddr, 19, 13, __val)
+#define SET_EARLYMODE_LEN1_2(__paddr, __val)                                   \
+       SET_BITS_TO_LE_4BYTE(__paddr + 4, 0, 2, __val)
+#define SET_EARLYMODE_LEN2(__paddr, __val)                                     \
+       SET_BITS_TO_LE_4BYTE(__paddr + 4, 2, 15, __val)
+#define SET_EARLYMODE_LEN2_1(__paddr, __val)                                   \
+       SET_BITS_TO_LE_4BYTE(__paddr, 2, 4, __val)
+#define SET_EARLYMODE_LEN2_2(__paddr, __val)                                   \
+       SET_BITS_TO_LE_4BYTE(__paddr + 4, 0, 8, __val)
+#define SET_EARLYMODE_LEN3(__paddr, __val)                                     \
+       SET_BITS_TO_LE_4BYTE(__paddr + 4, 17, 15, __val)
+#define SET_EARLYMODE_LEN4(__paddr, __val)                                     \
+       SET_BITS_TO_LE_4BYTE(__paddr + 4, 20, 12, __val)
+
+/* TX/RX buffer descriptor */
+
+/* for Txfilldescroptor8822be, fill the desc content. */
+#define SET_TXBUFFER_DESC_LEN_WITH_OFFSET(__pdesc, __offset, __val)            \
+       SET_BITS_TO_LE_4BYTE((__pdesc) + ((__offset) * 16), 0, 16, __val)
+#define SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(__pdesc, __offset, __val)          \
+       SET_BITS_TO_LE_4BYTE((__pdesc) + ((__offset) * 16), 31, 1, __val)
+#define SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(__pdesc, __offset, __val)        \
+       SET_BITS_TO_LE_4BYTE((__pdesc) + ((__offset) * 16) + 4, 0, 32, __val)
+#define SET_TXBUFFER_DESC_ADD_HIGH_WITH_OFFSET(pbd, off, val, dma64)          \
+       (dma64 ? SET_BITS_TO_LE_4BYTE((pbd) + ((off) * 16) + 8, 0, 32, val) : 0)
+#define GET_TXBUFFER_DESC_ADDR_LOW(__pdesc, __offset)                          \
+       LE_BITS_TO_4BYTE((__pdesc) + ((__offset) * 16) + 4, 0, 32)
+#define GET_TXBUFFER_DESC_ADDR_HIGH(pbd, off, dma64)                          \
+       (dma64 ? LE_BITS_TO_4BYTE((pbd) + ((off) * 16) + 8, 0, 32) : 0)
+
+/* Dword 0 */
+#define SET_TX_BUFF_DESC_LEN_0(__pdesc, __val)                                 \
+       SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val)
+#define SET_TX_BUFF_DESC_PSB(__pdesc, __val)                                   \
+       SET_BITS_TO_LE_4BYTE(__pdesc, 16, 15, __val)
+#define SET_TX_BUFF_DESC_OWN(__pdesc, __val)                                   \
+       SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+
+/* Dword 1 */
+#define SET_TX_BUFF_DESC_ADDR_LOW_0(__pdesc, __val)                            \
+       SET_BITS_TO_LE_4BYTE((__pdesc) + 4, 0, 32, __val)
+/* Dword 2 */
+#define SET_TX_BUFF_DESC_ADDR_HIGH_0(bdesc, val, dma64)                               \
+       SET_TXBUFFER_DESC_ADD_HIGH_WITH_OFFSET(bdesc, 0, val, dma64)
+/* Dword 3 / RESERVED 0 */
+
+/* RX buffer  */
+
+/* DWORD 0 */
+#define SET_RX_BUFFER_DESC_DATA_LENGTH(__rx_status_desc, __val)                \
+       SET_BITS_TO_LE_4BYTE(__rx_status_desc, 0, 14, __val)
+#define SET_RX_BUFFER_DESC_LS(__rx_status_desc, __val)                         \
+       SET_BITS_TO_LE_4BYTE(__rx_status_desc, 15, 1, __val)
+#define SET_RX_BUFFER_DESC_FS(__rx_status_desc, __val)                         \
+       SET_BITS_TO_LE_4BYTE(__rx_status_desc, 16, 1, __val)
+#define SET_RX_BUFFER_DESC_TOTAL_LENGTH(__rx_status_desc, __val)               \
+       SET_BITS_TO_LE_4BYTE(__rx_status_desc, 16, 15, __val)
+
+#define GET_RX_BUFFER_DESC_OWN(__rx_status_desc)                               \
+       LE_BITS_TO_4BYTE(__rx_status_desc, 31, 1)
+#define GET_RX_BUFFER_DESC_LS(__rx_status_desc)                                \
+       LE_BITS_TO_4BYTE(__rx_status_desc, 15, 1)
+#define GET_RX_BUFFER_DESC_FS(__rx_status_desc)                                \
+       LE_BITS_TO_4BYTE(__rx_status_desc, 16, 1)
+#define GET_RX_BUFFER_DESC_TOTAL_LENGTH(__rx_status_desc)                      \
+       LE_BITS_TO_4BYTE(__rx_status_desc, 16, 15)
+
+/* DWORD 1 */
+#define SET_RX_BUFFER_PHYSICAL_LOW(__rx_status_desc, __val)                    \
+       SET_BITS_TO_LE_4BYTE(__rx_status_desc + 4, 0, 32, __val)
+
+/* DWORD 2 */
+#define SET_RX_BUFFER_PHYSICAL_HIGH(__rx_status_desc, __val, dma64)            \
+       (dma64 ? SET_BITS_TO_LE_4BYTE((__rx_status_desc) + 8, 0, 32, __val) : 0)
+
+#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size)                              \
+       do {                                                                   \
+               if (_size > TX_DESC_NEXT_DESC_OFFSET)                          \
+                       memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET);          \
+               else                                                           \
+                       memset(__pdesc, 0, _size);                             \
+       } while (0)
+
+void rtl8822be_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc,
+                              u8 queue_index);
+u16 rtl8822be_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw,
+                                       u8 queue_index);
+u16 rtl8822be_get_available_desc(struct ieee80211_hw *hw, u8 queue_index);
+void rtl8822be_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, u8 *tx_bd_desc,
+                                  u8 *desc, u8 queue_index,
+                                  struct sk_buff *skb, dma_addr_t addr);
+
+void rtl8822be_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+                           u8 *pdesc_tx, u8 *pbd_desc_tx,
+                           struct ieee80211_tx_info *info,
+                           struct ieee80211_sta *sta, struct sk_buff *skb,
+                           u8 hw_queue, struct rtl_tcb_desc *ptcb_desc);
+void rtl8822be_tx_fill_special_desc(struct ieee80211_hw *hw, u8 *pdesc,
+                                   u8 *pbd_desc, struct sk_buff *skb,
+                                   u8 hw_queue);
+bool rtl8822be_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *status,
+                            struct ieee80211_rx_status *rx_status, u8 *pdesc,
+                            struct sk_buff *skb);
+void rtl8822be_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
+                       u8 desc_name, u8 *val);
+u64 rtl8822be_get_desc(struct ieee80211_hw *hw,
+                      u8 *pdesc, bool istx, u8 desc_name);
+bool rtl8822be_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue,
+                                u16 index);
+void rtl8822be_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
+void rtl8822be_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
+                              bool firstseg, bool lastseg,
+                              struct sk_buff *skb);
+u32 rtl8822be_rx_command_packet(struct ieee80211_hw *hw,
+                               const struct rtl_stats *status,
+                               struct sk_buff *skb);
+#endif