--- /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