rtw88: import Realtek's rtw88 driver

Import rtw88 based on wireless-testing at
5d5d68bcff1f7ff27ba0b938a4df5849849b47e3 with adjustments for FreeBSD.

While our version of the driver has knowledge about the incapablity
of DMA above 4GB we do see errors if people have more than that
often already showing when laoding firmware.
The problem for that is currently believed to be outside this driver
so importing it anyway for now.

Given the lack of full license texts on non-local files this is
imported under the draft policy for handling SPDX files (D29226). [1]

Approved by:	core (imp) [1]
MFC after:	2 weeks
This commit is contained in:
Bjoern A. Zeeb 2022-03-30 21:54:04 +00:00
parent ad93649d23
commit 2774f20680
62 changed files with 116201 additions and 0 deletions

414
sys/contrib/dev/rtw88/bf.c Normal file
View File

@ -0,0 +1,414 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation.
*/
#include "main.h"
#include "reg.h"
#include "bf.h"
#include "debug.h"
void rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
{
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
struct rtw_bfee *bfee = &rtwvif->bfee;
struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
if (bfee->role == RTW_BFEE_NONE)
return;
if (bfee->role == RTW_BFEE_MU)
bfinfo->bfer_mu_cnt--;
else if (bfee->role == RTW_BFEE_SU)
bfinfo->bfer_su_cnt--;
rtw_chip_config_bfee(rtwdev, rtwvif, bfee, false);
bfee->role = RTW_BFEE_NONE;
}
void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
{
struct ieee80211_hw *hw = rtwdev->hw;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
struct rtw_bfee *bfee = &rtwvif->bfee;
struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
struct rtw_chip_info *chip = rtwdev->chip;
struct ieee80211_sta *sta;
struct ieee80211_sta_vht_cap *vht_cap;
struct ieee80211_sta_vht_cap *ic_vht_cap;
const u8 *bssid = bss_conf->bssid;
u32 sound_dim;
u8 i;
if (!(chip->band & RTW_BAND_5G))
return;
rcu_read_lock();
sta = ieee80211_find_sta(vif, bssid);
if (!sta) {
#if defined(__linux__)
rtw_warn(rtwdev, "failed to find station entry for bss %pM\n",
bssid);
#elif defined(__FreeBSD__)
rtw_warn(rtwdev, "failed to find station entry for bss %6D\n",
bssid, ":");
#endif
goto out_unlock;
}
ic_vht_cap = &hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap;
vht_cap = &sta->vht_cap;
if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
(vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
if (bfinfo->bfer_mu_cnt >= chip->bfer_mu_max_num) {
rtw_dbg(rtwdev, RTW_DBG_BF, "mu bfer number over limit\n");
goto out_unlock;
}
ether_addr_copy(bfee->mac_addr, bssid);
bfee->role = RTW_BFEE_MU;
bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7);
bfee->aid = bss_conf->aid;
bfinfo->bfer_mu_cnt++;
rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true);
} else if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) &&
(vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
if (bfinfo->bfer_su_cnt >= chip->bfer_su_max_num) {
rtw_dbg(rtwdev, RTW_DBG_BF, "su bfer number over limit\n");
goto out_unlock;
}
sound_dim = vht_cap->cap &
IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
ether_addr_copy(bfee->mac_addr, bssid);
bfee->role = RTW_BFEE_SU;
bfee->sound_dim = (u8)sound_dim;
bfee->g_id = 0;
bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7);
bfinfo->bfer_su_cnt++;
for (i = 0; i < chip->bfer_su_max_num; i++) {
if (!test_bit(i, bfinfo->bfer_su_reg_maping)) {
set_bit(i, bfinfo->bfer_su_reg_maping);
bfee->su_reg_index = i;
break;
}
}
rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true);
}
out_unlock:
rcu_read_unlock();
}
void rtw_bf_init_bfer_entry_mu(struct rtw_dev *rtwdev,
struct mu_bfer_init_para *param)
{
u16 mu_bf_ctl = 0;
u8 *addr = param->bfer_address;
int i;
for (i = 0; i < ETH_ALEN; i++)
rtw_write8(rtwdev, REG_ASSOCIATED_BFMER0_INFO + i, addr[i]);
rtw_write16(rtwdev, REG_ASSOCIATED_BFMER0_INFO + 6, param->paid);
rtw_write16(rtwdev, REG_TX_CSI_RPT_PARAM_BW20, param->csi_para);
mu_bf_ctl = rtw_read16(rtwdev, REG_WMAC_MU_BF_CTL) & 0xC000;
mu_bf_ctl |= param->my_aid | (param->csi_length_sel << 12);
rtw_write16(rtwdev, REG_WMAC_MU_BF_CTL, mu_bf_ctl);
}
void rtw_bf_cfg_sounding(struct rtw_dev *rtwdev, struct rtw_vif *vif,
enum rtw_trx_desc_rate rate)
{
u32 psf_ctl = 0;
u8 csi_rsc = 0x1;
psf_ctl = rtw_read32(rtwdev, REG_BBPSF_CTRL) |
BIT_WMAC_USE_NDPARATE |
(csi_rsc << 13);
rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM,
RTW_SND_CTRL_SOUNDING);
rtw_write8(rtwdev, REG_SND_PTCL_CTRL + 3, 0x26);
rtw_write8_clr(rtwdev, REG_RXFLTMAP1, BIT_RXFLTMAP1_BF_REPORT_POLL);
rtw_write8_clr(rtwdev, REG_RXFLTMAP4, BIT_RXFLTMAP4_BF_REPORT_POLL);
if (vif->net_type == RTW_NET_AP_MODE)
rtw_write32(rtwdev, REG_BBPSF_CTRL, psf_ctl | BIT(12));
else
rtw_write32(rtwdev, REG_BBPSF_CTRL, psf_ctl & ~BIT(12));
}
void rtw_bf_cfg_mu_bfee(struct rtw_dev *rtwdev, struct cfg_mumimo_para *param)
{
u8 mu_tbl_sel;
u8 mu_valid;
mu_valid = rtw_read8(rtwdev, REG_MU_TX_CTL) &
~BIT_MASK_R_MU_TABLE_VALID;
rtw_write8(rtwdev, REG_MU_TX_CTL,
(mu_valid | BIT(0) | BIT(1)) & ~(BIT(7)));
mu_tbl_sel = rtw_read8(rtwdev, REG_MU_TX_CTL + 1) & 0xF8;
rtw_write8(rtwdev, REG_MU_TX_CTL + 1, mu_tbl_sel);
rtw_write32(rtwdev, REG_MU_STA_GID_VLD, param->given_gid_tab[0]);
rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO, param->given_user_pos[0]);
rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO + 4,
param->given_user_pos[1]);
rtw_write8(rtwdev, REG_MU_TX_CTL + 1, mu_tbl_sel | 1);
rtw_write32(rtwdev, REG_MU_STA_GID_VLD, param->given_gid_tab[1]);
rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO, param->given_user_pos[2]);
rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO + 4,
param->given_user_pos[3]);
}
void rtw_bf_del_bfer_entry_mu(struct rtw_dev *rtwdev)
{
rtw_write32(rtwdev, REG_ASSOCIATED_BFMER0_INFO, 0);
rtw_write32(rtwdev, REG_ASSOCIATED_BFMER0_INFO + 4, 0);
rtw_write16(rtwdev, REG_WMAC_MU_BF_CTL, 0);
rtw_write8(rtwdev, REG_MU_TX_CTL, 0);
}
void rtw_bf_del_sounding(struct rtw_dev *rtwdev)
{
rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, 0);
}
void rtw_bf_enable_bfee_su(struct rtw_dev *rtwdev, struct rtw_vif *vif,
struct rtw_bfee *bfee)
{
u8 nc_index = hweight8(rtwdev->hal.antenna_rx) - 1;
u8 nr_index = bfee->sound_dim;
u8 grouping = 0, codebookinfo = 1, coefficientsize = 3;
u32 addr_bfer_info, addr_csi_rpt, csi_param;
u8 i;
rtw_dbg(rtwdev, RTW_DBG_BF, "config as an su bfee\n");
switch (bfee->su_reg_index) {
case 1:
addr_bfer_info = REG_ASSOCIATED_BFMER1_INFO;
addr_csi_rpt = REG_TX_CSI_RPT_PARAM_BW20 + 2;
break;
case 0:
default:
addr_bfer_info = REG_ASSOCIATED_BFMER0_INFO;
addr_csi_rpt = REG_TX_CSI_RPT_PARAM_BW20;
break;
}
/* Sounding protocol control */
rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM,
RTW_SND_CTRL_SOUNDING);
/* MAC address/Partial AID of Beamformer */
for (i = 0; i < ETH_ALEN; i++)
rtw_write8(rtwdev, addr_bfer_info + i, bfee->mac_addr[i]);
csi_param = (u16)((coefficientsize << 10) |
(codebookinfo << 8) |
(grouping << 6) |
(nr_index << 3) |
nc_index);
rtw_write16(rtwdev, addr_csi_rpt, csi_param);
/* ndp rx standby timer */
rtw_write8(rtwdev, REG_SND_PTCL_CTRL + 3, RTW_NDP_RX_STANDBY_TIME);
}
EXPORT_SYMBOL(rtw_bf_enable_bfee_su);
/* nc index: 1 2T2R 0 1T1R
* nr index: 1 use Nsts 0 use reg setting
* codebookinfo: 1 802.11ac 3 802.11n
*/
void rtw_bf_enable_bfee_mu(struct rtw_dev *rtwdev, struct rtw_vif *vif,
struct rtw_bfee *bfee)
{
struct rtw_bf_info *bf_info = &rtwdev->bf_info;
struct mu_bfer_init_para param;
u8 nc_index = hweight8(rtwdev->hal.antenna_rx) - 1;
u8 nr_index = 1;
u8 grouping = 0, codebookinfo = 1, coefficientsize = 0;
u32 csi_param;
rtw_dbg(rtwdev, RTW_DBG_BF, "config as an mu bfee\n");
csi_param = (u16)((coefficientsize << 10) |
(codebookinfo << 8) |
(grouping << 6) |
(nr_index << 3) |
nc_index);
rtw_dbg(rtwdev, RTW_DBG_BF, "nc=%d nr=%d group=%d codebookinfo=%d coefficientsize=%d\n",
nc_index, nr_index, grouping, codebookinfo,
coefficientsize);
param.paid = bfee->p_aid;
param.csi_para = csi_param;
param.my_aid = bfee->aid & 0xfff;
param.csi_length_sel = HAL_CSI_SEG_4K;
ether_addr_copy(param.bfer_address, bfee->mac_addr);
rtw_bf_init_bfer_entry_mu(rtwdev, &param);
bf_info->cur_csi_rpt_rate = DESC_RATE6M;
rtw_bf_cfg_sounding(rtwdev, vif, DESC_RATE6M);
/* accept action_no_ack */
rtw_write16_set(rtwdev, REG_RXFLTMAP0, BIT_RXFLTMAP0_ACTIONNOACK);
/* accept NDPA and BF report poll */
rtw_write16_set(rtwdev, REG_RXFLTMAP1, BIT_RXFLTMAP1_BF);
}
EXPORT_SYMBOL(rtw_bf_enable_bfee_mu);
void rtw_bf_remove_bfee_su(struct rtw_dev *rtwdev,
struct rtw_bfee *bfee)
{
struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
rtw_dbg(rtwdev, RTW_DBG_BF, "remove as a su bfee\n");
rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM,
RTW_SND_CTRL_REMOVE);
switch (bfee->su_reg_index) {
case 0:
rtw_write32(rtwdev, REG_ASSOCIATED_BFMER0_INFO, 0);
rtw_write16(rtwdev, REG_ASSOCIATED_BFMER0_INFO + 4, 0);
rtw_write16(rtwdev, REG_TX_CSI_RPT_PARAM_BW20, 0);
break;
case 1:
rtw_write32(rtwdev, REG_ASSOCIATED_BFMER1_INFO, 0);
rtw_write16(rtwdev, REG_ASSOCIATED_BFMER1_INFO + 4, 0);
rtw_write16(rtwdev, REG_TX_CSI_RPT_PARAM_BW20 + 2, 0);
break;
}
clear_bit(bfee->su_reg_index, bfinfo->bfer_su_reg_maping);
bfee->su_reg_index = 0xFF;
}
EXPORT_SYMBOL(rtw_bf_remove_bfee_su);
void rtw_bf_remove_bfee_mu(struct rtw_dev *rtwdev,
struct rtw_bfee *bfee)
{
struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM,
RTW_SND_CTRL_REMOVE);
rtw_bf_del_bfer_entry_mu(rtwdev);
if (bfinfo->bfer_su_cnt == 0 && bfinfo->bfer_mu_cnt == 0)
rtw_bf_del_sounding(rtwdev);
}
EXPORT_SYMBOL(rtw_bf_remove_bfee_mu);
void rtw_bf_set_gid_table(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf)
{
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
struct rtw_bfee *bfee = &rtwvif->bfee;
struct cfg_mumimo_para param;
if (bfee->role != RTW_BFEE_MU) {
rtw_dbg(rtwdev, RTW_DBG_BF, "this vif is not mu bfee\n");
return;
}
param.grouping_bitmap = 0;
param.mu_tx_en = 0;
memset(param.sounding_sts, 0, 6);
memcpy(param.given_gid_tab, conf->mu_group.membership, 8);
memcpy(param.given_user_pos, conf->mu_group.position, 16);
rtw_dbg(rtwdev, RTW_DBG_BF, "STA0: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n",
param.given_gid_tab[0], param.given_user_pos[0],
param.given_user_pos[1]);
rtw_dbg(rtwdev, RTW_DBG_BF, "STA1: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n",
param.given_gid_tab[1], param.given_user_pos[2],
param.given_user_pos[3]);
rtw_bf_cfg_mu_bfee(rtwdev, &param);
}
EXPORT_SYMBOL(rtw_bf_set_gid_table);
void rtw_bf_phy_init(struct rtw_dev *rtwdev)
{
u8 tmp8;
u32 tmp32;
u8 retry_limit = 0xA;
u8 ndpa_rate = 0x10;
u8 ack_policy = 3;
tmp32 = rtw_read32(rtwdev, REG_MU_TX_CTL);
/* Enable P1 aggr new packet according to P0 transfer time */
tmp32 |= BIT_MU_P1_WAIT_STATE_EN;
/* MU Retry Limit */
tmp32 &= ~BIT_MASK_R_MU_RL;
tmp32 |= (retry_limit << BIT_SHIFT_R_MU_RL) & BIT_MASK_R_MU_RL;
/* Disable Tx MU-MIMO until sounding done */
tmp32 &= ~BIT_EN_MU_MIMO;
/* Clear validity of MU STAs */
tmp32 &= ~BIT_MASK_R_MU_TABLE_VALID;
rtw_write32(rtwdev, REG_MU_TX_CTL, tmp32);
/* MU-MIMO Option as default value */
tmp8 = ack_policy << BIT_SHIFT_WMAC_TXMU_ACKPOLICY;
tmp8 |= BIT_WMAC_TXMU_ACKPOLICY_EN;
rtw_write8(rtwdev, REG_WMAC_MU_BF_OPTION, tmp8);
/* MU-MIMO Control as default value */
rtw_write16(rtwdev, REG_WMAC_MU_BF_CTL, 0);
/* Set MU NDPA rate & BW source */
rtw_write32_set(rtwdev, REG_TXBF_CTRL, BIT_USE_NDPA_PARAMETER);
/* Set NDPA Rate */
rtw_write8(rtwdev, REG_NDPA_OPT_CTRL, ndpa_rate);
rtw_write32_mask(rtwdev, REG_BBPSF_CTRL, BIT_MASK_CSI_RATE,
DESC_RATE6M);
}
EXPORT_SYMBOL(rtw_bf_phy_init);
void rtw_bf_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
u8 fixrate_en, u8 *new_rate)
{
u32 csi_cfg;
u16 cur_rrsr;
csi_cfg = rtw_read32(rtwdev, REG_BBPSF_CTRL) & ~BIT_MASK_CSI_RATE;
cur_rrsr = rtw_read16(rtwdev, REG_RRSR);
if (rssi >= 40) {
if (cur_rate != DESC_RATE54M) {
cur_rrsr |= BIT(DESC_RATE54M);
csi_cfg |= (DESC_RATE54M & BIT_MASK_CSI_RATE_VAL) <<
BIT_SHIFT_CSI_RATE;
rtw_write16(rtwdev, REG_RRSR, cur_rrsr);
rtw_write32(rtwdev, REG_BBPSF_CTRL, csi_cfg);
}
*new_rate = DESC_RATE54M;
} else {
if (cur_rate != DESC_RATE24M) {
cur_rrsr &= ~BIT(DESC_RATE54M);
csi_cfg |= (DESC_RATE54M & BIT_MASK_CSI_RATE_VAL) <<
BIT_SHIFT_CSI_RATE;
rtw_write16(rtwdev, REG_RRSR, cur_rrsr);
rtw_write32(rtwdev, REG_BBPSF_CTRL, csi_cfg);
}
*new_rate = DESC_RATE24M;
}
}
EXPORT_SYMBOL(rtw_bf_cfg_csi_rate);

117
sys/contrib/dev/rtw88/bf.h Normal file
View File

@ -0,0 +1,117 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation.
*/
#ifndef __RTW_BF_H_
#define __RTW_BF_H_
#define REG_TXBF_CTRL 0x042C
#define REG_RRSR 0x0440
#define REG_NDPA_OPT_CTRL 0x045F
#define REG_ASSOCIATED_BFMER0_INFO 0x06E4
#define REG_ASSOCIATED_BFMER1_INFO 0x06EC
#define REG_TX_CSI_RPT_PARAM_BW20 0x06F4
#define REG_SND_PTCL_CTRL 0x0718
#define BIT_DIS_CHK_VHTSIGB_CRC BIT(6)
#define BIT_DIS_CHK_VHTSIGA_CRC BIT(5)
#define BIT_MASK_BEAMFORM (GENMASK(4, 0) | BIT(7))
#define REG_MU_TX_CTL 0x14C0
#define REG_MU_STA_GID_VLD 0x14C4
#define REG_MU_STA_USER_POS_INFO 0x14C8
#define REG_CSI_RRSR 0x1678
#define REG_WMAC_MU_BF_OPTION 0x167C
#define REG_WMAC_MU_BF_CTL 0x1680
#define BIT_WMAC_USE_NDPARATE BIT(30)
#define BIT_WMAC_TXMU_ACKPOLICY_EN BIT(6)
#define BIT_USE_NDPA_PARAMETER BIT(30)
#define BIT_MU_P1_WAIT_STATE_EN BIT(16)
#define BIT_EN_MU_MIMO BIT(7)
#define R_MU_RL 0xf
#define BIT_SHIFT_R_MU_RL 12
#define BIT_SHIFT_WMAC_TXMU_ACKPOLICY 4
#define BIT_SHIFT_CSI_RATE 24
#define BIT_MASK_R_MU_RL (R_MU_RL << BIT_SHIFT_R_MU_RL)
#define BIT_MASK_R_MU_TABLE_VALID 0x3f
#define BIT_MASK_CSI_RATE_VAL 0x3F
#define BIT_MASK_CSI_RATE (BIT_MASK_CSI_RATE_VAL << BIT_SHIFT_CSI_RATE)
#define BIT_RXFLTMAP0_ACTIONNOACK BIT(14)
#define BIT_RXFLTMAP1_BF (BIT(4) | BIT(5))
#define BIT_RXFLTMAP1_BF_REPORT_POLL BIT(4)
#define BIT_RXFLTMAP4_BF_REPORT_POLL BIT(4)
#define RTW_NDP_RX_STANDBY_TIME 0x70
#define RTW_SND_CTRL_REMOVE 0x98
#define RTW_SND_CTRL_SOUNDING 0x9B
enum csi_seg_len {
HAL_CSI_SEG_4K = 0,
HAL_CSI_SEG_8K = 1,
HAL_CSI_SEG_11K = 2,
};
struct cfg_mumimo_para {
u8 sounding_sts[6];
u16 grouping_bitmap;
u8 mu_tx_en;
u32 given_gid_tab[2];
u32 given_user_pos[4];
};
struct mu_bfer_init_para {
u16 paid;
u16 csi_para;
u16 my_aid;
enum csi_seg_len csi_length_sel;
u8 bfer_address[ETH_ALEN];
};
void rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf);
void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf);
void rtw_bf_init_bfer_entry_mu(struct rtw_dev *rtwdev,
struct mu_bfer_init_para *param);
void rtw_bf_cfg_sounding(struct rtw_dev *rtwdev, struct rtw_vif *vif,
enum rtw_trx_desc_rate rate);
void rtw_bf_cfg_mu_bfee(struct rtw_dev *rtwdev, struct cfg_mumimo_para *param);
void rtw_bf_del_bfer_entry_mu(struct rtw_dev *rtwdev);
void rtw_bf_del_sounding(struct rtw_dev *rtwdev);
void rtw_bf_enable_bfee_su(struct rtw_dev *rtwdev, struct rtw_vif *vif,
struct rtw_bfee *bfee);
void rtw_bf_enable_bfee_mu(struct rtw_dev *rtwdev, struct rtw_vif *vif,
struct rtw_bfee *bfee);
void rtw_bf_remove_bfee_su(struct rtw_dev *rtwdev, struct rtw_bfee *bfee);
void rtw_bf_remove_bfee_mu(struct rtw_dev *rtwdev, struct rtw_bfee *bfee);
void rtw_bf_set_gid_table(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf);
void rtw_bf_phy_init(struct rtw_dev *rtwdev);
void rtw_bf_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
u8 fixrate_en, u8 *new_rate);
static inline void rtw_chip_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif,
struct rtw_bfee *bfee, bool enable)
{
if (rtwdev->chip->ops->config_bfee)
rtwdev->chip->ops->config_bfee(rtwdev, vif, bfee, enable);
}
static inline void rtw_chip_set_gid_table(struct rtw_dev *rtwdev,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf)
{
if (rtwdev->chip->ops->set_gid_table)
rtwdev->chip->ops->set_gid_table(rtwdev, vif, conf);
}
static inline void rtw_chip_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
u8 fixrate_en, u8 *new_rate)
{
if (rtwdev->chip->ops->cfg_csi_rate)
rtwdev->chip->ops->cfg_csi_rate(rtwdev, rssi, cur_rate,
fixrate_en, new_rate);
}
#endif

3922
sys/contrib/dev/rtw88/coex.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,417 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_COEX_H__
#define __RTW_COEX_H__
#define COEX_CCK_2 0x1
#define COEX_RESP_ACK_BY_WL_FW 0x1
#define COEX_REQUEST_TIMEOUT msecs_to_jiffies(10)
#define COEX_MIN_DELAY 10 /* delay unit in ms */
#define COEX_RFK_TIMEOUT 600 /* RFK timeout in ms */
#define COEX_RF_OFF 0x0
#define COEX_RF_ON 0x1
#define COEX_H2C69_WL_LEAKAP 0xc
#define PARA1_H2C69_DIS_5MS 0x1
#define PARA1_H2C69_EN_5MS 0x0
#define COEX_H2C69_TDMA_SLOT 0xb
#define PARA1_H2C69_TDMA_4SLOT 0xc1
#define PARA1_H2C69_TDMA_2SLOT 0x1
#define PARA1_H2C69_TBTT_TIMES GENMASK(5, 0)
#define PARA1_H2C69_TBTT_DIV100 BIT(7)
#define COEX_H2C69_TOGGLE_TABLE_A 0xd
#define COEX_H2C69_TOGGLE_TABLE_B 0x7
#define TDMA_4SLOT BIT(8)
#define TDMA_TIMER_TYPE_2SLOT 0
#define TDMA_TIMER_TYPE_4SLOT 3
#define COEX_RSSI_STEP 4
#define COEX_RSSI_HIGH(rssi) \
({ typeof(rssi) __rssi__ = rssi; \
(__rssi__ == COEX_RSSI_STATE_HIGH || \
__rssi__ == COEX_RSSI_STATE_STAY_HIGH ? true : false); })
#define COEX_RSSI_MEDIUM(rssi) \
({ typeof(rssi) __rssi__ = rssi; \
(__rssi__ == COEX_RSSI_STATE_MEDIUM || \
__rssi__ == COEX_RSSI_STATE_STAY_MEDIUM ? true : false); })
#define COEX_RSSI_LOW(rssi) \
({ typeof(rssi) __rssi__ = rssi; \
(__rssi__ == COEX_RSSI_STATE_LOW || \
__rssi__ == COEX_RSSI_STATE_STAY_LOW ? true : false); })
#define GET_COEX_RESP_BT_SUPP_VER(payload) \
le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(39, 32))
#define GET_COEX_RESP_BT_SUPP_FEAT(payload) \
le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(39, 24))
#define GET_COEX_RESP_BT_PATCH_VER(payload) \
le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(55, 24))
#define GET_COEX_RESP_BT_REG_VAL(payload) \
le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(39, 24))
#define GET_COEX_RESP_BT_SCAN_TYPE(payload) \
le64_get_bits(*((__le64 *)(payload)), GENMASK(31, 24))
enum coex_mp_info_op {
BT_MP_INFO_OP_PATCH_VER = 0x00,
BT_MP_INFO_OP_READ_REG = 0x11,
BT_MP_INFO_OP_SUPP_FEAT = 0x2a,
BT_MP_INFO_OP_SUPP_VER = 0x2b,
BT_MP_INFO_OP_SCAN_TYPE = 0x2d,
BT_MP_INFO_OP_LNA_CONSTRAINT = 0x32,
};
enum coex_set_ant_phase {
COEX_SET_ANT_INIT,
COEX_SET_ANT_WONLY,
COEX_SET_ANT_WOFF,
COEX_SET_ANT_2G,
COEX_SET_ANT_5G,
COEX_SET_ANT_POWERON,
COEX_SET_ANT_2G_WLBT,
COEX_SET_ANT_2G_FREERUN,
COEX_SET_ANT_MAX
};
enum coex_runreason {
COEX_RSN_2GSCANSTART = 0,
COEX_RSN_5GSCANSTART = 1,
COEX_RSN_SCANFINISH = 2,
COEX_RSN_2GSWITCHBAND = 3,
COEX_RSN_5GSWITCHBAND = 4,
COEX_RSN_2GCONSTART = 5,
COEX_RSN_5GCONSTART = 6,
COEX_RSN_2GCONFINISH = 7,
COEX_RSN_5GCONFINISH = 8,
COEX_RSN_2GMEDIA = 9,
COEX_RSN_5GMEDIA = 10,
COEX_RSN_MEDIADISCON = 11,
COEX_RSN_BTINFO = 12,
COEX_RSN_LPS = 13,
COEX_RSN_WLSTATUS = 14,
COEX_RSN_BTSTATUS = 15,
COEX_RSN_MAX
};
enum coex_lte_coex_table_type {
COEX_CTT_WL_VS_LTE,
COEX_CTT_BT_VS_LTE,
};
enum coex_gnt_setup_state {
COEX_GNT_SET_HW_PTA = 0x0,
COEX_GNT_SET_SW_LOW = 0x1,
COEX_GNT_SET_SW_HIGH = 0x3,
};
enum coex_ext_ant_switch_pos_type {
COEX_SWITCH_TO_BT,
COEX_SWITCH_TO_WLG,
COEX_SWITCH_TO_WLA,
COEX_SWITCH_TO_NOCARE,
COEX_SWITCH_TO_WLG_BT,
COEX_SWITCH_TO_MAX
};
enum coex_ext_ant_switch_ctrl_type {
COEX_SWITCH_CTRL_BY_BBSW,
COEX_SWITCH_CTRL_BY_PTA,
COEX_SWITCH_CTRL_BY_ANTDIV,
COEX_SWITCH_CTRL_BY_MAC,
COEX_SWITCH_CTRL_BY_BT,
COEX_SWITCH_CTRL_BY_FW,
COEX_SWITCH_CTRL_MAX
};
enum coex_algorithm {
COEX_ALGO_NOPROFILE = 0,
COEX_ALGO_HFP = 1,
COEX_ALGO_HID = 2,
COEX_ALGO_A2DP = 3,
COEX_ALGO_PAN = 4,
COEX_ALGO_A2DP_HID = 5,
COEX_ALGO_A2DP_PAN = 6,
COEX_ALGO_PAN_HID = 7,
COEX_ALGO_A2DP_PAN_HID = 8,
COEX_ALGO_MAX
};
enum coex_bt_profile {
BPM_NOPROFILE = 0,
BPM_HFP = BIT(0),
BPM_HID = BIT(1),
BPM_A2DP = BIT(2),
BPM_PAN = BIT(3),
BPM_HID_HFP = BPM_HID | BPM_HFP,
BPM_A2DP_HFP = BPM_A2DP | BPM_HFP,
BPM_A2DP_HID = BPM_A2DP | BPM_HID,
BPM_A2DP_HID_HFP = BPM_A2DP | BPM_HID | BPM_HFP,
BPM_PAN_HFP = BPM_PAN | BPM_HFP,
BPM_PAN_HID = BPM_PAN | BPM_HID,
BPM_PAN_HID_HFP = BPM_PAN | BPM_HID | BPM_HFP,
BPM_PAN_A2DP = BPM_PAN | BPM_A2DP,
BPM_PAN_A2DP_HFP = BPM_PAN | BPM_A2DP | BPM_HFP,
BPM_PAN_A2DP_HID = BPM_PAN | BPM_A2DP | BPM_HID,
BPM_PAN_A2DP_HID_HFP = BPM_PAN | BPM_A2DP | BPM_HID | BPM_HFP,
};
enum coex_wl_link_mode {
COEX_WLINK_2G1PORT = 0x0,
COEX_WLINK_5G = 0x3,
COEX_WLINK_MAX
};
enum coex_wl2bt_scoreboard {
COEX_SCBD_ACTIVE = BIT(0),
COEX_SCBD_ONOFF = BIT(1),
COEX_SCBD_SCAN = BIT(2),
COEX_SCBD_UNDERTEST = BIT(3),
COEX_SCBD_RXGAIN = BIT(4),
COEX_SCBD_BT_RFK = BIT(5),
COEX_SCBD_WLBUSY = BIT(6),
COEX_SCBD_EXTFEM = BIT(8),
COEX_SCBD_TDMA = BIT(9),
COEX_SCBD_FIX2M = BIT(10),
COEX_SCBD_ALL = GENMASK(15, 0),
};
enum coex_power_save_type {
COEX_PS_WIFI_NATIVE = 0,
COEX_PS_LPS_ON = 1,
COEX_PS_LPS_OFF = 2,
};
enum coex_rssi_state {
COEX_RSSI_STATE_HIGH,
COEX_RSSI_STATE_MEDIUM,
COEX_RSSI_STATE_LOW,
COEX_RSSI_STATE_STAY_HIGH,
COEX_RSSI_STATE_STAY_MEDIUM,
COEX_RSSI_STATE_STAY_LOW,
};
enum coex_notify_type_ips {
COEX_IPS_LEAVE = 0x0,
COEX_IPS_ENTER = 0x1,
};
enum coex_notify_type_lps {
COEX_LPS_DISABLE = 0x0,
COEX_LPS_ENABLE = 0x1,
};
enum coex_notify_type_scan {
COEX_SCAN_FINISH,
COEX_SCAN_START,
COEX_SCAN_START_2G,
COEX_SCAN_START_5G,
};
enum coex_notify_type_switchband {
COEX_NOT_SWITCH,
COEX_SWITCH_TO_24G,
COEX_SWITCH_TO_5G,
COEX_SWITCH_TO_24G_NOFORSCAN,
};
enum coex_notify_type_associate {
COEX_ASSOCIATE_FINISH,
COEX_ASSOCIATE_START,
COEX_ASSOCIATE_5G_FINISH,
COEX_ASSOCIATE_5G_START,
};
enum coex_notify_type_media_status {
COEX_MEDIA_DISCONNECT,
COEX_MEDIA_CONNECT,
COEX_MEDIA_CONNECT_5G,
};
enum coex_bt_status {
COEX_BTSTATUS_NCON_IDLE = 0,
COEX_BTSTATUS_CON_IDLE = 1,
COEX_BTSTATUS_INQ_PAGE = 2,
COEX_BTSTATUS_ACL_BUSY = 3,
COEX_BTSTATUS_SCO_BUSY = 4,
COEX_BTSTATUS_ACL_SCO_BUSY = 5,
COEX_BTSTATUS_MAX
};
enum coex_wl_tput_dir {
COEX_WL_TPUT_TX = 0x0,
COEX_WL_TPUT_RX = 0x1,
COEX_WL_TPUT_MAX
};
enum coex_wl_priority_mask {
COEX_WLPRI_RX_RSP = 2,
COEX_WLPRI_TX_RSP = 3,
COEX_WLPRI_TX_BEACON = 4,
COEX_WLPRI_TX_OFDM = 11,
COEX_WLPRI_TX_CCK = 12,
COEX_WLPRI_TX_BEACONQ = 27,
COEX_WLPRI_RX_CCK = 28,
COEX_WLPRI_RX_OFDM = 29,
COEX_WLPRI_MAX
};
enum coex_commom_chip_setup {
COEX_CSETUP_INIT_HW = 0x0,
COEX_CSETUP_ANT_SWITCH = 0x1,
COEX_CSETUP_GNT_FIX = 0x2,
COEX_CSETUP_GNT_DEBUG = 0x3,
COEX_CSETUP_RFE_TYPE = 0x4,
COEX_CSETUP_COEXINFO_HW = 0x5,
COEX_CSETUP_WL_TX_POWER = 0x6,
COEX_CSETUP_WL_RX_GAIN = 0x7,
COEX_CSETUP_WLAN_ACT_IPS = 0x8,
COEX_CSETUP_MAX
};
enum coex_indirect_reg_type {
COEX_INDIRECT_1700 = 0x0,
COEX_INDIRECT_7C0 = 0x1,
COEX_INDIRECT_MAX
};
enum coex_pstdma_type {
COEX_PSTDMA_FORCE_LPSOFF = 0x0,
COEX_PSTDMA_FORCE_LPSON = 0x1,
COEX_PSTDMA_MAX
};
enum coex_btrssi_type {
COEX_BTRSSI_RATIO = 0x0,
COEX_BTRSSI_DBM = 0x1,
COEX_BTRSSI_MAX
};
struct coex_table_para {
u32 bt;
u32 wl;
};
struct coex_tdma_para {
u8 para[5];
};
struct coex_5g_afh_map {
u32 wl_5g_ch;
u8 bt_skip_ch;
u8 bt_skip_span;
};
struct coex_rf_para {
u8 wl_pwr_dec_lvl;
u8 bt_pwr_dec_lvl;
bool wl_low_gain_en;
u8 bt_lna_lvl;
};
static inline void rtw_coex_set_init(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
chip->ops->coex_set_init(rtwdev);
}
static inline
void rtw_coex_set_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, u8 pos_type)
{
struct rtw_chip_info *chip = rtwdev->chip;
if (!chip->ops->coex_set_ant_switch)
return;
chip->ops->coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
}
static inline void rtw_coex_set_gnt_fix(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
chip->ops->coex_set_gnt_fix(rtwdev);
}
static inline void rtw_coex_set_gnt_debug(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
chip->ops->coex_set_gnt_debug(rtwdev);
}
static inline void rtw_coex_set_rfe_type(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
chip->ops->coex_set_rfe_type(rtwdev);
}
static inline void rtw_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
{
struct rtw_chip_info *chip = rtwdev->chip;
chip->ops->coex_set_wl_tx_power(rtwdev, wl_pwr);
}
static inline
void rtw_coex_set_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
{
struct rtw_chip_info *chip = rtwdev->chip;
chip->ops->coex_set_wl_rx_gain(rtwdev, low_gain);
}
void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb);
u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr);
void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
u32 mask, u32 val);
void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set);
void rtw_coex_bt_relink_work(struct work_struct *work);
void rtw_coex_bt_reenable_work(struct work_struct *work);
void rtw_coex_defreeze_work(struct work_struct *work);
void rtw_coex_wl_remain_work(struct work_struct *work);
void rtw_coex_bt_remain_work(struct work_struct *work);
void rtw_coex_wl_connecting_work(struct work_struct *work);
void rtw_coex_bt_multi_link_remain_work(struct work_struct *work);
void rtw_coex_wl_ccklock_work(struct work_struct *work);
void rtw_coex_power_on_setting(struct rtw_dev *rtwdev);
void rtw_coex_power_off_setting(struct rtw_dev *rtwdev);
void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only);
void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type);
void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m);
static inline bool rtw_coex_disabled(struct rtw_dev *rtwdev)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
return coex_stat->bt_disabled;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_DEBUG_H
#define __RTW_DEBUG_H
enum rtw_debug_mask {
RTW_DBG_PCI = 0x00000001,
RTW_DBG_TX = 0x00000002,
RTW_DBG_RX = 0x00000004,
RTW_DBG_PHY = 0x00000008,
RTW_DBG_FW = 0x00000010,
RTW_DBG_EFUSE = 0x00000020,
RTW_DBG_COEX = 0x00000040,
RTW_DBG_RFK = 0x00000080,
RTW_DBG_REGD = 0x00000100,
RTW_DBG_DEBUGFS = 0x00000200,
RTW_DBG_PS = 0x00000400,
RTW_DBG_BF = 0x00000800,
RTW_DBG_WOW = 0x00001000,
RTW_DBG_CFO = 0x00002000,
RTW_DBG_PATH_DIV = 0x00004000,
RTW_DBG_ADAPTIVITY = 0x00008000,
RTW_DBG_HW_SCAN = 0x00010000,
#if defined(__FreeBSD__)
RTW_DBG_IO_RW = 0x80000000,
#endif
RTW_DBG_ALL = 0xffffffff
};
#ifdef CONFIG_RTW88_DEBUGFS
void rtw_debugfs_init(struct rtw_dev *rtwdev);
void rtw_debugfs_get_simple_phy_info(struct seq_file *m);
#else
static inline void rtw_debugfs_init(struct rtw_dev *rtwdev) {}
#endif /* CONFIG_RTW88_DEBUGFS */
#ifdef CONFIG_RTW88_DEBUG
__printf(3, 4)
void __rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
const char *fmt, ...);
#if defined(__linux__)
#define rtw_dbg(rtwdev, a...) __rtw_dbg(rtwdev, ##a)
#elif defined(__FreeBSD__)
#define rtw_dbg(rtwdev, ...) __rtw_dbg(rtwdev, __VA_ARGS__)
#endif
#else
static inline void rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
const char *fmt, ...) {}
#endif /* CONFIG_RTW88_DEBUG */
#define rtw_info(rtwdev, a...) dev_info(rtwdev->dev, ##a)
#define rtw_warn(rtwdev, a...) dev_warn(rtwdev->dev, ##a)
#define rtw_err(rtwdev, a...) dev_err(rtwdev->dev, ##a)
#endif

View File

@ -0,0 +1,187 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include <linux/iopoll.h>
#include "main.h"
#include "efuse.h"
#include "reg.h"
#include "debug.h"
#define RTW_EFUSE_BANK_WIFI 0x0
static void switch_efuse_bank(struct rtw_dev *rtwdev)
{
rtw_write32_mask(rtwdev, REG_LDO_EFUSE_CTRL, BIT_MASK_EFUSE_BANK_SEL,
RTW_EFUSE_BANK_WIFI);
}
#define invalid_efuse_header(hdr1, hdr2) \
((hdr1) == 0xff || (((hdr1) & 0x1f) == 0xf && (hdr2) == 0xff))
#define invalid_efuse_content(word_en, i) \
(((word_en) & BIT(i)) != 0x0)
#define get_efuse_blk_idx_2_byte(hdr1, hdr2) \
((((hdr2) & 0xf0) >> 1) | (((hdr1) >> 5) & 0x07))
#define get_efuse_blk_idx_1_byte(hdr1) \
(((hdr1) & 0xf0) >> 4)
#define block_idx_to_logical_idx(blk_idx, i) \
(((blk_idx) << 3) + ((i) << 1))
/* efuse header format
*
* | 7 5 4 0 | 7 4 3 0 | 15 8 7 0 |
* block[2:0] 0 1111 block[6:3] word_en[3:0] byte0 byte1
* | header 1 (optional) | header 2 | word N |
*
* word_en: 4 bits each word. 0 -> write; 1 -> not write
* N: 1~4, depends on word_en
*/
static int rtw_dump_logical_efuse_map(struct rtw_dev *rtwdev, u8 *phy_map,
u8 *log_map)
{
u32 physical_size = rtwdev->efuse.physical_size;
u32 protect_size = rtwdev->efuse.protect_size;
u32 logical_size = rtwdev->efuse.logical_size;
u32 phy_idx, log_idx;
u8 hdr1, hdr2;
u8 blk_idx;
u8 word_en;
int i;
for (phy_idx = 0; phy_idx < physical_size - protect_size;) {
hdr1 = phy_map[phy_idx];
hdr2 = phy_map[phy_idx + 1];
if (invalid_efuse_header(hdr1, hdr2))
break;
if ((hdr1 & 0x1f) == 0xf) {
/* 2-byte header format */
blk_idx = get_efuse_blk_idx_2_byte(hdr1, hdr2);
word_en = hdr2 & 0xf;
phy_idx += 2;
} else {
/* 1-byte header format */
blk_idx = get_efuse_blk_idx_1_byte(hdr1);
word_en = hdr1 & 0xf;
phy_idx += 1;
}
for (i = 0; i < 4; i++) {
if (invalid_efuse_content(word_en, i))
continue;
log_idx = block_idx_to_logical_idx(blk_idx, i);
if (phy_idx + 1 > physical_size - protect_size ||
log_idx + 1 > logical_size)
return -EINVAL;
log_map[log_idx] = phy_map[phy_idx];
log_map[log_idx + 1] = phy_map[phy_idx + 1];
phy_idx += 2;
}
}
return 0;
}
static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
{
struct rtw_chip_info *chip = rtwdev->chip;
u32 size = rtwdev->efuse.physical_size;
u32 efuse_ctl;
u32 addr;
u32 cnt;
rtw_chip_efuse_grant_on(rtwdev);
switch_efuse_bank(rtwdev);
/* disable 2.5V LDO */
chip->ops->cfg_ldo25(rtwdev, false);
efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
for (addr = 0; addr < size; addr++) {
efuse_ctl &= ~(BIT_MASK_EF_DATA | BITS_EF_ADDR);
efuse_ctl |= (addr & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR;
rtw_write32(rtwdev, REG_EFUSE_CTRL, efuse_ctl & (~BIT_EF_FLAG));
cnt = 1000000;
do {
udelay(1);
efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
if (--cnt == 0)
return -EBUSY;
} while (!(efuse_ctl & BIT_EF_FLAG));
*(map + addr) = (u8)(efuse_ctl & BIT_MASK_EF_DATA);
}
rtw_chip_efuse_grant_off(rtwdev);
return 0;
}
int rtw_read8_physical_efuse(struct rtw_dev *rtwdev, u16 addr, u8 *data)
{
u32 efuse_ctl;
int ret;
rtw_write32_mask(rtwdev, REG_EFUSE_CTRL, 0x3ff00, addr);
rtw_write32_clr(rtwdev, REG_EFUSE_CTRL, BIT_EF_FLAG);
ret = read_poll_timeout(rtw_read32, efuse_ctl, efuse_ctl & BIT_EF_FLAG,
1000, 100000, false, rtwdev, REG_EFUSE_CTRL);
if (ret) {
*data = EFUSE_READ_FAIL;
return ret;
}
*data = rtw_read8(rtwdev, REG_EFUSE_CTRL);
return 0;
}
EXPORT_SYMBOL(rtw_read8_physical_efuse);
int rtw_parse_efuse_map(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_efuse *efuse = &rtwdev->efuse;
u32 phy_size = efuse->physical_size;
u32 log_size = efuse->logical_size;
u8 *phy_map = NULL;
u8 *log_map = NULL;
int ret = 0;
phy_map = kmalloc(phy_size, GFP_KERNEL);
log_map = kmalloc(log_size, GFP_KERNEL);
if (!phy_map || !log_map) {
ret = -ENOMEM;
goto out_free;
}
ret = rtw_dump_physical_efuse_map(rtwdev, phy_map);
if (ret) {
rtw_err(rtwdev, "failed to dump efuse physical map\n");
goto out_free;
}
memset(log_map, 0xff, log_size);
ret = rtw_dump_logical_efuse_map(rtwdev, phy_map, log_map);
if (ret) {
rtw_err(rtwdev, "failed to dump efuse logical map\n");
goto out_free;
}
ret = chip->ops->read_efuse(rtwdev, log_map);
if (ret) {
rtw_err(rtwdev, "failed to read efuse map\n");
goto out_free;
}
out_free:
kfree(log_map);
kfree(phy_map);
return ret;
}

View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_EFUSE_H__
#define __RTW_EFUSE_H__
#define EFUSE_HW_CAP_IGNORE 0
#define EFUSE_HW_CAP_PTCL_VHT 3
#define EFUSE_HW_CAP_SUPP_BW80 7
#define EFUSE_HW_CAP_SUPP_BW40 6
#define EFUSE_READ_FAIL 0xff
#define GET_EFUSE_HW_CAP_HCI(hw_cap) \
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(3, 0))
#define GET_EFUSE_HW_CAP_BW(hw_cap) \
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(18, 16))
#define GET_EFUSE_HW_CAP_NSS(hw_cap) \
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(20, 19))
#define GET_EFUSE_HW_CAP_ANT_NUM(hw_cap) \
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(23, 21))
#define GET_EFUSE_HW_CAP_PTCL(hw_cap) \
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(27, 26))
int rtw_parse_efuse_map(struct rtw_dev *rtwdev);
int rtw_read8_physical_efuse(struct rtw_dev *rtwdev, u16 addr, u8 *data);
#endif

2167
sys/contrib/dev/rtw88/fw.c Normal file

File diff suppressed because it is too large Load Diff

832
sys/contrib/dev/rtw88/fw.h Normal file
View File

@ -0,0 +1,832 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_FW_H_
#define __RTW_FW_H_
#define H2C_PKT_SIZE 32
#define H2C_PKT_HDR_SIZE 8
/* FW bin information */
#define FW_HDR_SIZE 64
#define FW_HDR_CHKSUM_SIZE 8
#define FW_NLO_INFO_CHECK_SIZE 4
#define FIFO_PAGE_SIZE_SHIFT 12
#define FIFO_PAGE_SIZE 4096
#define FIFO_DUMP_ADDR 0x8000
#define DLFW_PAGE_SIZE_SHIFT_LEGACY 12
#define DLFW_PAGE_SIZE_LEGACY 0x1000
#define DLFW_BLK_SIZE_SHIFT_LEGACY 2
#define DLFW_BLK_SIZE_LEGACY 4
#define FW_START_ADDR_LEGACY 0x1000
#define BCN_LOSS_CNT 10
#define BCN_FILTER_NOTIFY_SIGNAL_CHANGE 0
#define BCN_FILTER_CONNECTION_LOSS 1
#define BCN_FILTER_CONNECTED 2
#define BCN_FILTER_NOTIFY_BEACON_LOSS 3
#define SCAN_NOTIFY_TIMEOUT msecs_to_jiffies(10)
#define RTW_CHANNEL_TIME 45
#define RTW_OFF_CHAN_TIME 100
#define RTW_PASS_CHAN_TIME 105
#define RTW_DFS_CHAN_TIME 20
#define RTW_CH_INFO_SIZE 4
#define RTW_EX_CH_INFO_SIZE 3
#define RTW_EX_CH_INFO_HDR_SIZE 2
#define RTW_SCAN_WIDTH 0
#define RTW_PRI_CH_IDX 1
#define RTW_PROBE_PG_CNT 2
enum rtw_c2h_cmd_id {
C2H_CCX_TX_RPT = 0x03,
C2H_BT_INFO = 0x09,
C2H_BT_MP_INFO = 0x0b,
C2H_RA_RPT = 0x0c,
C2H_HW_FEATURE_REPORT = 0x19,
C2H_WLAN_INFO = 0x27,
C2H_WLAN_RFON = 0x32,
C2H_BCN_FILTER_NOTIFY = 0x36,
C2H_ADAPTIVITY = 0x37,
C2H_SCAN_RESULT = 0x38,
C2H_HW_FEATURE_DUMP = 0xfd,
C2H_HALMAC = 0xff,
};
enum rtw_c2h_cmd_id_ext {
C2H_SCAN_STATUS_RPT = 0x3,
C2H_CCX_RPT = 0x0f,
C2H_CHAN_SWITCH = 0x22,
};
struct rtw_c2h_cmd {
u8 id;
u8 seq;
u8 payload[];
} __packed;
struct rtw_c2h_adaptivity {
u8 density;
u8 igi;
u8 l2h_th_init;
u8 l2h;
u8 h2l;
u8 option;
} __packed;
enum rtw_rsvd_packet_type {
RSVD_BEACON,
RSVD_DUMMY,
RSVD_PS_POLL,
RSVD_PROBE_RESP,
RSVD_NULL,
RSVD_QOS_NULL,
RSVD_LPS_PG_DPK,
RSVD_LPS_PG_INFO,
RSVD_PROBE_REQ,
RSVD_NLO_INFO,
RSVD_CH_INFO,
};
enum rtw_fw_rf_type {
FW_RF_1T2R = 0,
FW_RF_2T4R = 1,
FW_RF_2T2R = 2,
FW_RF_2T3R = 3,
FW_RF_1T1R = 4,
FW_RF_2T2R_GREEN = 5,
FW_RF_3T3R = 6,
FW_RF_3T4R = 7,
FW_RF_4T4R = 8,
FW_RF_MAX_TYPE = 0xF,
};
enum rtw_fw_feature {
FW_FEATURE_SIG = BIT(0),
FW_FEATURE_LPS_C2H = BIT(1),
FW_FEATURE_LCLK = BIT(2),
FW_FEATURE_PG = BIT(3),
FW_FEATURE_TX_WAKE = BIT(4),
FW_FEATURE_BCN_FILTER = BIT(5),
FW_FEATURE_NOTIFY_SCAN = BIT(6),
FW_FEATURE_ADAPTIVITY = BIT(7),
FW_FEATURE_SCAN_OFFLOAD = BIT(8),
FW_FEATURE_MAX = BIT(31),
};
enum rtw_beacon_filter_offload_mode {
BCN_FILTER_OFFLOAD_MODE_0 = 0,
BCN_FILTER_OFFLOAD_MODE_1,
BCN_FILTER_OFFLOAD_MODE_2,
BCN_FILTER_OFFLOAD_MODE_3,
BCN_FILTER_OFFLOAD_MODE_DEFAULT = BCN_FILTER_OFFLOAD_MODE_0,
};
struct rtw_coex_info_req {
u8 seq;
u8 op_code;
u8 para1;
u8 para2;
u8 para3;
};
struct rtw_iqk_para {
u8 clear;
u8 segment_iqk;
};
struct rtw_lps_pg_dpk_hdr {
u16 dpk_path_ok;
u8 dpk_txagc[2];
u16 dpk_gs[2];
u32 coef[2][20];
u8 dpk_ch;
} __packed;
struct rtw_lps_pg_info_hdr {
u8 macid;
u8 mbssid;
u8 pattern_count;
u8 mu_tab_group_id;
u8 sec_cam_count;
u8 tx_bu_page_count;
u16 rsvd;
u8 sec_cam[MAX_PG_CAM_BACKUP_NUM];
} __packed;
struct rtw_rsvd_page {
/* associated with each vif */
struct list_head vif_list;
struct rtw_vif *rtwvif;
/* associated when build rsvd page */
struct list_head build_list;
struct sk_buff *skb;
enum rtw_rsvd_packet_type type;
u8 page;
bool add_txdesc;
struct cfg80211_ssid *ssid;
u16 probe_req_size;
};
enum rtw_keep_alive_pkt_type {
KEEP_ALIVE_NULL_PKT = 0,
KEEP_ALIVE_ARP_RSP = 1,
};
struct rtw_nlo_info_hdr {
u8 nlo_count;
u8 hidden_ap_count;
u8 rsvd1[2];
u8 pattern_check[FW_NLO_INFO_CHECK_SIZE];
u8 rsvd2[8];
u8 ssid_len[16];
u8 chiper[16];
u8 rsvd3[16];
u8 location[8];
} __packed;
enum rtw_packet_type {
RTW_PACKET_PROBE_REQ = 0x00,
RTW_PACKET_UNDEFINE = 0x7FFFFFFF,
};
struct rtw_fw_wow_keep_alive_para {
bool adopt;
u8 pkt_type;
u8 period; /* unit: sec */
};
struct rtw_fw_wow_disconnect_para {
bool adopt;
u8 period; /* unit: sec */
u8 retry_count;
};
enum rtw_channel_type {
RTW_CHANNEL_PASSIVE,
RTW_CHANNEL_ACTIVE,
RTW_CHANNEL_RADAR,
};
enum rtw_scan_extra_id {
RTW_SCAN_EXTRA_ID_DFS,
};
enum rtw_scan_extra_info {
RTW_SCAN_EXTRA_ACTION_SCAN,
};
enum rtw_scan_report_code {
RTW_SCAN_REPORT_SUCCESS = 0x00,
RTW_SCAN_REPORT_ERR_PHYDM = 0x01,
RTW_SCAN_REPORT_ERR_ID = 0x02,
RTW_SCAN_REPORT_ERR_TX = 0x03,
RTW_SCAN_REPORT_CANCELED = 0x10,
RTW_SCAN_REPORT_CANCELED_EXT = 0x11,
RTW_SCAN_REPORT_FW_DISABLED = 0xF0,
};
enum rtw_scan_notify_id {
RTW_SCAN_NOTIFY_ID_PRESWITCH = 0x00,
RTW_SCAN_NOTIFY_ID_POSTSWITCH = 0x01,
RTW_SCAN_NOTIFY_ID_PROBE_PRETX = 0x02,
RTW_SCAN_NOTIFY_ID_PROBE_ISSUETX = 0x03,
RTW_SCAN_NOTIFY_ID_NULL0_PRETX = 0x04,
RTW_SCAN_NOTIFY_ID_NULL0_ISSUETX = 0x05,
RTW_SCAN_NOTIFY_ID_NULL0_POSTTX = 0x06,
RTW_SCAN_NOTIFY_ID_NULL1_PRETX = 0x07,
RTW_SCAN_NOTIFY_ID_NULL1_ISSUETX = 0x08,
RTW_SCAN_NOTIFY_ID_NULL1_POSTTX = 0x09,
RTW_SCAN_NOTIFY_ID_DWELLEXT = 0x0A,
};
enum rtw_scan_notify_status {
RTW_SCAN_NOTIFY_STATUS_SUCCESS = 0x00,
RTW_SCAN_NOTIFY_STATUS_FAILURE = 0x01,
RTW_SCAN_NOTIFY_STATUS_RESOURCE = 0x02,
RTW_SCAN_NOTIFY_STATUS_TIMEOUT = 0x03,
};
struct rtw_ch_switch_option {
u8 periodic_option;
u32 tsf_high;
u32 tsf_low;
u8 dest_ch_en;
u8 absolute_time_en;
u8 dest_ch;
u8 normal_period;
u8 normal_period_sel;
u8 normal_cycle;
u8 slow_period;
u8 slow_period_sel;
u8 nlo_en;
bool switch_en;
bool back_op_en;
};
struct rtw_fw_hdr {
__le16 signature;
u8 category;
u8 function;
__le16 version; /* 0x04 */
u8 subversion;
u8 subindex;
__le32 rsvd; /* 0x08 */
__le32 feature; /* 0x0C */
u8 month; /* 0x10 */
u8 day;
u8 hour;
u8 min;
__le16 year; /* 0x14 */
__le16 rsvd3;
u8 mem_usage; /* 0x18 */
u8 rsvd4[3];
__le16 h2c_fmt_ver; /* 0x1C */
__le16 rsvd5;
__le32 dmem_addr; /* 0x20 */
__le32 dmem_size;
__le32 rsvd6;
__le32 rsvd7;
__le32 imem_size; /* 0x30 */
__le32 emem_size;
__le32 emem_addr;
__le32 imem_addr;
} __packed;
struct rtw_fw_hdr_legacy {
__le16 signature;
u8 category;
u8 function;
__le16 version; /* 0x04 */
u8 subversion1;
u8 subversion2;
u8 month; /* 0x08 */
u8 day;
u8 hour;
u8 minute;
__le16 size;
__le16 rsvd2;
__le32 idx; /* 0x10 */
__le32 rsvd3;
__le32 rsvd4; /* 0x18 */
__le32 rsvd5;
} __packed;
/* C2H */
#define GET_CCX_REPORT_SEQNUM_V0(c2h_payload) (c2h_payload[6] & 0xfc)
#define GET_CCX_REPORT_STATUS_V0(c2h_payload) (c2h_payload[0] & 0xc0)
#define GET_CCX_REPORT_SEQNUM_V1(c2h_payload) (c2h_payload[8] & 0xfc)
#define GET_CCX_REPORT_STATUS_V1(c2h_payload) (c2h_payload[9] & 0xc0)
#define GET_SCAN_REPORT_RETURN_CODE(c2h_payload) (c2h_payload[2] & 0xff)
#define GET_CHAN_SWITCH_CENTRAL_CH(c2h_payload) (c2h_payload[2])
#define GET_CHAN_SWITCH_ID(c2h_payload) (c2h_payload[3])
#define GET_CHAN_SWITCH_STATUS(c2h_payload) (c2h_payload[4])
#define GET_RA_REPORT_RATE(c2h_payload) (c2h_payload[0] & 0x7f)
#define GET_RA_REPORT_SGI(c2h_payload) ((c2h_payload[0] & 0x80) >> 7)
#define GET_RA_REPORT_BW(c2h_payload) (c2h_payload[6])
#define GET_RA_REPORT_MACID(c2h_payload) (c2h_payload[1])
#define GET_BCN_FILTER_NOTIFY_TYPE(c2h_payload) (c2h_payload[1] & 0xf)
#define GET_BCN_FILTER_NOTIFY_EVENT(c2h_payload) (c2h_payload[1] & 0x10)
#define GET_BCN_FILTER_NOTIFY_RSSI(c2h_payload) (c2h_payload[2] - 100)
/* PKT H2C */
#define H2C_PKT_CMD_ID 0xFF
#define H2C_PKT_CATEGORY 0x01
#define H2C_PKT_GENERAL_INFO 0x0D
#define H2C_PKT_PHYDM_INFO 0x11
#define H2C_PKT_IQK 0x0E
#define H2C_PKT_CH_SWITCH 0x02
#define H2C_PKT_UPDATE_PKT 0x0C
#define H2C_PKT_SCAN_OFFLOAD 0x19
#define H2C_PKT_CH_SWITCH_LEN 0x20
#define H2C_PKT_UPDATE_PKT_LEN 0x4
#define SET_PKT_H2C_CATEGORY(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(6, 0))
#define SET_PKT_H2C_CMD_ID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_PKT_H2C_SUB_CMD_ID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 16))
#define SET_PKT_H2C_TOTAL_LEN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 0))
static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
{
SET_PKT_H2C_CATEGORY(h2c_pkt, H2C_PKT_CATEGORY);
SET_PKT_H2C_CMD_ID(h2c_pkt, H2C_PKT_CMD_ID);
SET_PKT_H2C_SUB_CMD_ID(h2c_pkt, sub_id);
}
#define FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(31, 16))
#define GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16))
#define PHYDM_INFO_SET_REF_TYPE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(7, 0))
#define PHYDM_INFO_SET_RF_TYPE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8))
#define PHYDM_INFO_SET_CUT_VER(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16))
#define PHYDM_INFO_SET_RX_ANT_STATUS(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(27, 24))
#define PHYDM_INFO_SET_TX_ANT_STATUS(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 28))
#define IQK_SET_CLEAR(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(0))
#define IQK_SET_SEGMENT_IQK(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1))
#define CHSW_INFO_SET_CH(pkt, value) \
le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(7, 0))
#define CHSW_INFO_SET_PRI_CH_IDX(pkt, value) \
le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(11, 8))
#define CHSW_INFO_SET_BW(pkt, value) \
le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(15, 12))
#define CHSW_INFO_SET_TIMEOUT(pkt, value) \
le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(23, 16))
#define CHSW_INFO_SET_ACTION_ID(pkt, value) \
le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(30, 24))
#define CHSW_INFO_SET_EXTRA_INFO(pkt, value) \
le32p_replace_bits((__le32 *)(pkt) + 0x00, value, BIT(31))
#define CH_INFO_SET_CH(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x00, value, GENMASK(7, 0))
#define CH_INFO_SET_PRI_CH_IDX(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x01, value, GENMASK(3, 0))
#define CH_INFO_SET_BW(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x01, value, GENMASK(7, 4))
#define CH_INFO_SET_TIMEOUT(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x02, value, GENMASK(7, 0))
#define CH_INFO_SET_ACTION_ID(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x03, value, GENMASK(6, 0))
#define CH_INFO_SET_EXTRA_INFO(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x03, value, BIT(7))
#define EXTRA_CH_INFO_SET_ID(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x04, value, GENMASK(6, 0))
#define EXTRA_CH_INFO_SET_INFO(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x04, value, BIT(7))
#define EXTRA_CH_INFO_SET_SIZE(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x05, value, GENMASK(7, 0))
#define EXTRA_CH_INFO_SET_DFS_EXT_TIME(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x06, value, GENMASK(7, 0))
#define UPDATE_PKT_SET_SIZE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 0))
#define UPDATE_PKT_SET_PKT_ID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16))
#define UPDATE_PKT_SET_LOCATION(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 24))
#define CH_SWITCH_SET_START(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(0))
#define CH_SWITCH_SET_DEST_CH_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1))
#define CH_SWITCH_SET_ABSOLUTE_TIME(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(2))
#define CH_SWITCH_SET_PERIODIC_OPT(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(4, 3))
#define CH_SWITCH_SET_SCAN_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(5))
#define CH_SWITCH_SET_BACK_OP_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(6))
#define CH_SWITCH_SET_INFO_LOC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8))
#define CH_SWITCH_SET_CH_NUM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16))
#define CH_SWITCH_SET_PRI_CH_IDX(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(27, 24))
#define CH_SWITCH_SET_DEST_BW(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 28))
#define CH_SWITCH_SET_DEST_CH(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(7, 0))
#define CH_SWITCH_SET_NORMAL_PERIOD(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(13, 8))
#define CH_SWITCH_SET_NORMAL_PERIOD_SEL(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(15, 14))
#define CH_SWITCH_SET_SLOW_PERIOD(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(21, 16))
#define CH_SWITCH_SET_SLOW_PERIOD_SEL(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(23, 22))
#define CH_SWITCH_SET_NORMAL_CYCLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(31, 24))
#define CH_SWITCH_SET_TSF_HIGH(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x04, value, GENMASK(31, 0))
#define CH_SWITCH_SET_TSF_LOW(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(31, 0))
#define CH_SWITCH_SET_INFO_SIZE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x06, value, GENMASK(15, 0))
#define SCAN_OFFLOAD_SET_START(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(0))
#define SCAN_OFFLOAD_SET_BACK_OP_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1))
#define SCAN_OFFLOAD_SET_RANDOM_SEQ_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(2))
#define SCAN_OFFLOAD_SET_NO_CCK_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(3))
#define SCAN_OFFLOAD_SET_VERBOSE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(4))
#define SCAN_OFFLOAD_SET_CH_NUM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8))
#define SCAN_OFFLOAD_SET_CH_INFO_SIZE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 16))
#define SCAN_OFFLOAD_SET_CH_INFO_LOC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(7, 0))
#define SCAN_OFFLOAD_SET_OP_CH(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(15, 8))
#define SCAN_OFFLOAD_SET_OP_PRI_CH_IDX(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(19, 16))
#define SCAN_OFFLOAD_SET_OP_BW(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(23, 20))
#define SCAN_OFFLOAD_SET_OP_PORT_ID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(26, 24))
#define SCAN_OFFLOAD_SET_OP_DWELL_TIME(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x04, value, GENMASK(15, 0))
#define SCAN_OFFLOAD_SET_OP_GAP_TIME(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x04, value, GENMASK(31, 16))
#define SCAN_OFFLOAD_SET_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(3, 0))
#define SCAN_OFFLOAD_SET_SSID_NUM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(7, 4))
#define SCAN_OFFLOAD_SET_PKT_LOC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(15, 8))
/* Command H2C */
#define H2C_CMD_RSVD_PAGE 0x0
#define H2C_CMD_MEDIA_STATUS_RPT 0x01
#define H2C_CMD_SET_PWR_MODE 0x20
#define H2C_CMD_LPS_PG_INFO 0x2b
#define H2C_CMD_RA_INFO 0x40
#define H2C_CMD_RSSI_MONITOR 0x42
#define H2C_CMD_BCN_FILTER_OFFLOAD_P0 0x56
#define H2C_CMD_BCN_FILTER_OFFLOAD_P1 0x57
#define H2C_CMD_WL_PHY_INFO 0x58
#define H2C_CMD_SCAN 0x59
#define H2C_CMD_ADAPTIVITY 0x5A
#define H2C_CMD_COEX_TDMA_TYPE 0x60
#define H2C_CMD_QUERY_BT_INFO 0x61
#define H2C_CMD_FORCE_BT_TX_POWER 0x62
#define H2C_CMD_IGNORE_WLAN_ACTION 0x63
#define H2C_CMD_WL_CH_INFO 0x66
#define H2C_CMD_QUERY_BT_MP_INFO 0x67
#define H2C_CMD_BT_WIFI_CONTROL 0x69
#define H2C_CMD_WIFI_CALIBRATION 0x6d
#define H2C_CMD_KEEP_ALIVE 0x03
#define H2C_CMD_DISCONNECT_DECISION 0x04
#define H2C_CMD_WOWLAN 0x80
#define H2C_CMD_REMOTE_WAKE_CTRL 0x81
#define H2C_CMD_AOAC_GLOBAL_INFO 0x82
#define H2C_CMD_NLO_INFO 0x8C
#define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0))
#define MEDIA_STATUS_RPT_SET_OP_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define SET_WL_PHY_INFO_TX_TP(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(17, 8))
#define SET_WL_PHY_INFO_RX_TP(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(27, 18))
#define SET_WL_PHY_INFO_TX_RATE_DESC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
#define SET_WL_PHY_INFO_RX_RATE_DESC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
#define SET_WL_PHY_INFO_RX_EVM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16))
#define SET_BCN_FILTER_OFFLOAD_P1_MACID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_BCN_FILTER_OFFLOAD_P1_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(16))
#define SET_BCN_FILTER_OFFLOAD_P1_HYST(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(20, 17))
#define SET_BCN_FILTER_OFFLOAD_P1_OFFLOAD_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 21))
#define SET_BCN_FILTER_OFFLOAD_P1_THRESHOLD(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define SET_BCN_FILTER_OFFLOAD_P1_BCN_LOSS_CNT(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(3, 0))
#define SET_BCN_FILTER_OFFLOAD_P1_BCN_INTERVAL(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(13, 4))
#define SET_SCAN_START(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define SET_ADAPTIVITY_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(11, 8))
#define SET_ADAPTIVITY_OPTION(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 12))
#define SET_ADAPTIVITY_IGI(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define SET_ADAPTIVITY_L2H(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define SET_ADAPTIVITY_DENSITY(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
#define SET_PWR_MODE_SET_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(14, 8))
#define SET_PWR_MODE_SET_RLBM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(19, 16))
#define SET_PWR_MODE_SET_SMART_PS(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 20))
#define SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define SET_PWR_MODE_SET_PORT_ID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 5))
#define SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
#define LPS_PG_INFO_LOC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define LPS_PG_DPK_LOC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define LPS_PG_SEC_CAM_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define LPS_PG_PATTERN_CAM_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10))
#define SET_RSSI_INFO_MACID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_RSSI_INFO_RSSI(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define SET_RSSI_INFO_STBC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, BIT(1))
#define SET_RA_INFO_MACID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_RA_INFO_RATE_ID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(20, 16))
#define SET_RA_INFO_INIT_RA_LVL(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(22, 21))
#define SET_RA_INFO_SGI_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(23))
#define SET_RA_INFO_BW_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(25, 24))
#define SET_RA_INFO_LDPC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(26))
#define SET_RA_INFO_NO_UPDATE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(27))
#define SET_RA_INFO_VHT_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(29, 28))
#define SET_RA_INFO_DIS_PT(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(30))
#define SET_RA_INFO_RA_MASK0(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
#define SET_RA_INFO_RA_MASK1(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
#define SET_RA_INFO_RA_MASK2(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16))
#define SET_RA_INFO_RA_MASK3(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(31, 24))
#define SET_QUERY_BT_INFO(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define SET_WL_CH_INFO_LINK(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_WL_CH_INFO_CHNL(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define SET_WL_CH_INFO_BW(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define SET_BT_MP_INFO_SEQ(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 12))
#define SET_BT_MP_INFO_OP_CODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define SET_BT_MP_INFO_PARA1(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define SET_BT_MP_INFO_PARA2(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
#define SET_BT_MP_INFO_PARA3(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
#define SET_BT_TX_POWER_INDEX(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_IGNORE_WLAN_ACTION_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define SET_COEX_TDMA_TYPE_PARA1(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_COEX_TDMA_TYPE_PARA2(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define SET_COEX_TDMA_TYPE_PARA3(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define SET_COEX_TDMA_TYPE_PARA4(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
#define SET_COEX_TDMA_TYPE_PARA5(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
#define SET_BT_WIFI_CONTROL_OP_CODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_BT_WIFI_CONTROL_DATA1(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define SET_BT_WIFI_CONTROL_DATA2(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define SET_BT_WIFI_CONTROL_DATA3(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
#define SET_BT_WIFI_CONTROL_DATA4(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
#define SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16))
#define SET_KEEP_ALIVE_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define SET_KEEP_ALIVE_ADOPT(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9))
#define SET_KEEP_ALIVE_PKT_TYPE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10))
#define SET_KEEP_ALIVE_CHECK_PERIOD(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define SET_DISCONNECT_DECISION_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define SET_DISCONNECT_DECISION_ADOPT(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9))
#define SET_DISCONNECT_DECISION_CHECK_PERIOD(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define SET_DISCONNECT_DECISION_TRY_PKT_NUM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
#define SET_WOWLAN_FUNC_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define SET_WOWLAN_PATTERN_MATCH_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9))
#define SET_WOWLAN_MAGIC_PKT_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10))
#define SET_WOWLAN_UNICAST_PKT_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(11))
#define SET_WOWLAN_REKEY_WAKEUP_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(14))
#define SET_WOWLAN_DEAUTH_WAKEUP_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(15))
#define SET_REMOTE_WAKECTRL_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define SET_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(12))
#define SET_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define SET_NLO_FUN_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define SET_NLO_PS_32K(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9))
#define SET_NLO_IGNORE_SECURITY(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10))
#define SET_NLO_LOC_NLO_INFO(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
#define GET_FW_DUMP_LEN(_header) \
le32_get_bits(*((__le32 *)(_header) + 0x00), GENMASK(15, 0))
#define GET_FW_DUMP_SEQ(_header) \
le32_get_bits(*((__le32 *)(_header) + 0x00), GENMASK(22, 16))
#define GET_FW_DUMP_MORE(_header) \
le32_get_bits(*((__le32 *)(_header) + 0x00), BIT(23))
#define GET_FW_DUMP_VERSION(_header) \
le32_get_bits(*((__le32 *)(_header) + 0x00), GENMASK(31, 24))
#define GET_FW_DUMP_TLV_TYPE(_header) \
le32_get_bits(*((__le32 *)(_header) + 0x01), GENMASK(15, 0))
#define GET_FW_DUMP_TLV_LEN(_header) \
le32_get_bits(*((__le32 *)(_header) + 0x01), GENMASK(31, 16))
#define GET_FW_DUMP_TLV_VAL(_header) \
le32_get_bits(*((__le32 *)(_header) + 0x02), GENMASK(31, 0))
#define RFK_SET_INFORM_START(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb)
{
u32 pkt_offset;
pkt_offset = *((u32 *)skb->cb);
return (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
}
static inline bool rtw_fw_feature_check(struct rtw_fw_state *fw,
enum rtw_fw_feature feature)
{
return !!(fw->feature & feature);
}
void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
struct sk_buff *skb);
void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_fw_send_general_info(struct rtw_dev *rtwdev);
void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev);
void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para);
void rtw_fw_inform_rfk_status(struct rtw_dev *rtwdev, bool start);
void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev);
void rtw_fw_set_pg_info(struct rtw_dev *rtwdev);
void rtw_fw_query_bt_info(struct rtw_dev *rtwdev);
void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw);
void rtw_fw_query_bt_mp_info(struct rtw_dev *rtwdev,
struct rtw_coex_info_req *req);
void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl);
void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
u8 para1, u8 para2, u8 para3, u8 para4, u8 para5);
void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data);
void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn);
void rtw_fw_update_wl_phy_info(struct rtw_dev *rtwdev);
void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,
struct ieee80211_vif *vif);
int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
u8 *buf, u32 size);
void rtw_remove_rsvd_page(struct rtw_dev *rtwdev,
struct rtw_vif *rtwvif);
void rtw_add_rsvd_page_bcn(struct rtw_dev *rtwdev,
struct rtw_vif *rtwvif);
void rtw_add_rsvd_page_pno(struct rtw_dev *rtwdev,
struct rtw_vif *rtwvif);
void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev,
struct rtw_vif *rtwvif);
int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev);
void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev);
int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
u32 offset, u32 size, u32 *buf);
void rtw_fw_set_remote_wake_ctrl_cmd(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_set_wowlan_ctrl_cmd(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_set_keep_alive_cmd(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_set_disconnect_decision_cmd(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_set_aoac_global_info_cmd(struct rtw_dev *rtwdev,
u8 pairwise_key_enc,
u8 group_key_enc);
void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev,
struct cfg80211_ssid *ssid);
void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c);
void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev);
int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
u32 *buffer);
void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
void rtw_fw_adaptivity(struct rtw_dev *rtwdev);
void rtw_store_op_chan(struct rtw_dev *rtwdev);
void rtw_hw_scan_start(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_scan_request *req);
void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bool aborted);
int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bool enable);
void rtw_hw_scan_status_report(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_hw_scan_abort(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
#endif

277
sys/contrib/dev/rtw88/hci.h Normal file
View File

@ -0,0 +1,277 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_HCI_H__
#define __RTW_HCI_H__
/* ops for PCI, USB and SDIO */
struct rtw_hci_ops {
int (*tx_write)(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct sk_buff *skb);
void (*tx_kick_off)(struct rtw_dev *rtwdev);
void (*flush_queues)(struct rtw_dev *rtwdev, u32 queues, bool drop);
int (*setup)(struct rtw_dev *rtwdev);
int (*start)(struct rtw_dev *rtwdev);
void (*stop)(struct rtw_dev *rtwdev);
void (*deep_ps)(struct rtw_dev *rtwdev, bool enter);
void (*link_ps)(struct rtw_dev *rtwdev, bool enter);
void (*interface_cfg)(struct rtw_dev *rtwdev);
int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
u8 (*read8)(struct rtw_dev *rtwdev, u32 addr);
u16 (*read16)(struct rtw_dev *rtwdev, u32 addr);
u32 (*read32)(struct rtw_dev *rtwdev, u32 addr);
void (*write8)(struct rtw_dev *rtwdev, u32 addr, u8 val);
void (*write16)(struct rtw_dev *rtwdev, u32 addr, u16 val);
void (*write32)(struct rtw_dev *rtwdev, u32 addr, u32 val);
};
static inline int rtw_hci_tx_write(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct sk_buff *skb)
{
return rtwdev->hci.ops->tx_write(rtwdev, pkt_info, skb);
}
static inline void rtw_hci_tx_kick_off(struct rtw_dev *rtwdev)
{
return rtwdev->hci.ops->tx_kick_off(rtwdev);
}
static inline int rtw_hci_setup(struct rtw_dev *rtwdev)
{
return rtwdev->hci.ops->setup(rtwdev);
}
static inline int rtw_hci_start(struct rtw_dev *rtwdev)
{
return rtwdev->hci.ops->start(rtwdev);
}
static inline void rtw_hci_stop(struct rtw_dev *rtwdev)
{
rtwdev->hci.ops->stop(rtwdev);
}
static inline void rtw_hci_deep_ps(struct rtw_dev *rtwdev, bool enter)
{
rtwdev->hci.ops->deep_ps(rtwdev, enter);
}
static inline void rtw_hci_link_ps(struct rtw_dev *rtwdev, bool enter)
{
rtwdev->hci.ops->link_ps(rtwdev, enter);
}
static inline void rtw_hci_interface_cfg(struct rtw_dev *rtwdev)
{
rtwdev->hci.ops->interface_cfg(rtwdev);
}
static inline int
rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
{
return rtwdev->hci.ops->write_data_rsvd_page(rtwdev, buf, size);
}
static inline int
rtw_hci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
{
return rtwdev->hci.ops->write_data_h2c(rtwdev, buf, size);
}
static inline u8 rtw_read8(struct rtw_dev *rtwdev, u32 addr)
{
return rtwdev->hci.ops->read8(rtwdev, addr);
}
static inline u16 rtw_read16(struct rtw_dev *rtwdev, u32 addr)
{
return rtwdev->hci.ops->read16(rtwdev, addr);
}
static inline u32 rtw_read32(struct rtw_dev *rtwdev, u32 addr)
{
return rtwdev->hci.ops->read32(rtwdev, addr);
}
static inline void rtw_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
{
rtwdev->hci.ops->write8(rtwdev, addr, val);
}
static inline void rtw_write16(struct rtw_dev *rtwdev, u32 addr, u16 val)
{
rtwdev->hci.ops->write16(rtwdev, addr, val);
}
static inline void rtw_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
{
rtwdev->hci.ops->write32(rtwdev, addr, val);
}
static inline void rtw_write8_set(struct rtw_dev *rtwdev, u32 addr, u8 bit)
{
u8 val;
val = rtw_read8(rtwdev, addr);
rtw_write8(rtwdev, addr, val | bit);
}
static inline void rtw_write16_set(struct rtw_dev *rtwdev, u32 addr, u16 bit)
{
u16 val;
val = rtw_read16(rtwdev, addr);
rtw_write16(rtwdev, addr, val | bit);
}
static inline void rtw_write32_set(struct rtw_dev *rtwdev, u32 addr, u32 bit)
{
u32 val;
val = rtw_read32(rtwdev, addr);
rtw_write32(rtwdev, addr, val | bit);
}
static inline void rtw_write8_clr(struct rtw_dev *rtwdev, u32 addr, u8 bit)
{
u8 val;
val = rtw_read8(rtwdev, addr);
rtw_write8(rtwdev, addr, val & ~bit);
}
static inline void rtw_write16_clr(struct rtw_dev *rtwdev, u32 addr, u16 bit)
{
u16 val;
val = rtw_read16(rtwdev, addr);
rtw_write16(rtwdev, addr, val & ~bit);
}
static inline void rtw_write32_clr(struct rtw_dev *rtwdev, u32 addr, u32 bit)
{
u32 val;
val = rtw_read32(rtwdev, addr);
rtw_write32(rtwdev, addr, val & ~bit);
}
static inline u32
rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
u32 addr, u32 mask)
{
unsigned long flags;
u32 val;
spin_lock_irqsave(&rtwdev->rf_lock, flags);
val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask);
spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
return val;
}
static inline void
rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
u32 addr, u32 mask, u32 data)
{
unsigned long flags;
spin_lock_irqsave(&rtwdev->rf_lock, flags);
rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data);
spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
}
static inline u32
rtw_read32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask)
{
u32 shift = __ffs(mask);
u32 orig;
u32 ret;
orig = rtw_read32(rtwdev, addr);
ret = (orig & mask) >> shift;
return ret;
}
static inline u16
rtw_read16_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask)
{
u32 shift = __ffs(mask);
u32 orig;
u32 ret;
orig = rtw_read16(rtwdev, addr);
ret = (orig & mask) >> shift;
return ret;
}
static inline u8
rtw_read8_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask)
{
u32 shift = __ffs(mask);
u32 orig;
u32 ret;
orig = rtw_read8(rtwdev, addr);
ret = (orig & mask) >> shift;
return ret;
}
static inline void
rtw_write32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
{
u32 shift = __ffs(mask);
u32 orig;
u32 set;
WARN(addr & 0x3, "should be 4-byte aligned, addr = 0x%08x\n", addr);
orig = rtw_read32(rtwdev, addr);
set = (orig & ~mask) | ((data << shift) & mask);
rtw_write32(rtwdev, addr, set);
}
static inline void
rtw_write8_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u8 data)
{
u32 shift;
u8 orig, set;
mask &= 0xff;
shift = __ffs(mask);
orig = rtw_read8(rtwdev, addr);
set = (orig & ~mask) | ((data << shift) & mask);
rtw_write8(rtwdev, addr, set);
}
static inline enum rtw_hci_type rtw_hci_type(struct rtw_dev *rtwdev)
{
return rtwdev->hci.type;
}
static inline void rtw_hci_flush_queues(struct rtw_dev *rtwdev, u32 queues,
bool drop)
{
if (rtwdev->hci.ops->flush_queues)
rtwdev->hci.ops->flush_queues(rtwdev, queues, drop);
}
static inline void rtw_hci_flush_all_queues(struct rtw_dev *rtwdev, bool drop)
{
if (rtwdev->hci.ops->flush_queues)
rtwdev->hci.ops->flush_queues(rtwdev,
BIT(rtwdev->hw->queues) - 1,
drop);
}
#endif

1298
sys/contrib/dev/rtw88/mac.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_MAC_H__
#define __RTW_MAC_H__
#define RTW_HW_PORT_NUM 5
#define cut_version_to_mask(cut) (0x1 << ((cut) + 1))
#define SDIO_LOCAL_OFFSET 0x10250000
#define DDMA_POLLING_COUNT 1000
#define C2H_PKT_BUF 256
#define REPORT_BUF 128
#define PHY_STATUS_SIZE 4
#define ILLEGAL_KEY_GROUP 0xFAAAAA00
/* HW memory address */
#define OCPBASE_RXBUF_FW_88XX 0x18680000
#define OCPBASE_TXBUF_88XX 0x18780000
#define OCPBASE_ROM_88XX 0x00000000
#define OCPBASE_IMEM_88XX 0x00030000
#define OCPBASE_DMEM_88XX 0x00200000
#define OCPBASE_EMEM_88XX 0x00100000
#define RSVD_PG_DRV_NUM 16
#define RSVD_PG_H2C_EXTRAINFO_NUM 24
#define RSVD_PG_H2C_STATICINFO_NUM 8
#define RSVD_PG_H2CQ_NUM 8
#define RSVD_PG_CPU_INSTRUCTION_NUM 0
#define RSVD_PG_FW_TXBUF_NUM 4
void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
u8 primary_ch_idx);
int rtw_mac_power_on(struct rtw_dev *rtwdev);
void rtw_mac_power_off(struct rtw_dev *rtwdev);
int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw);
int rtw_mac_init(struct rtw_dev *rtwdev);
void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop);
int rtw_ddma_to_fw_fifo(struct rtw_dev *rtwdev, u32 ocp_src, u32 size);
static inline void rtw_mac_flush_all_queues(struct rtw_dev *rtwdev, bool drop)
{
rtw_mac_flush_queues(rtwdev, BIT(rtwdev->hw->queues) - 1, drop);
}
#endif

View File

@ -0,0 +1,899 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "sec.h"
#include "tx.h"
#include "fw.h"
#include "mac.h"
#include "coex.h"
#include "ps.h"
#include "reg.h"
#include "bf.h"
#include "debug.h"
#include "wow.h"
#include "sar.h"
static void rtw_ops_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
struct rtw_dev *rtwdev = hw->priv;
if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) {
ieee80211_free_txskb(hw, skb);
return;
}
rtw_tx(rtwdev, control, skb);
}
static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv;
if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
return;
spin_lock_bh(&rtwdev->txq_lock);
if (list_empty(&rtwtxq->list))
list_add_tail(&rtwtxq->list, &rtwdev->txqs);
spin_unlock_bh(&rtwdev->txq_lock);
queue_work(rtwdev->tx_wq, &rtwdev->tx_work);
}
static int rtw_ops_start(struct ieee80211_hw *hw)
{
struct rtw_dev *rtwdev = hw->priv;
int ret;
mutex_lock(&rtwdev->mutex);
ret = rtw_core_start(rtwdev);
mutex_unlock(&rtwdev->mutex);
return ret;
}
static void rtw_ops_stop(struct ieee80211_hw *hw)
{
struct rtw_dev *rtwdev = hw->priv;
mutex_lock(&rtwdev->mutex);
rtw_core_stop(rtwdev);
mutex_unlock(&rtwdev->mutex);
}
static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
{
struct rtw_dev *rtwdev = hw->priv;
int ret = 0;
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
!(hw->conf.flags & IEEE80211_CONF_IDLE)) {
ret = rtw_leave_ips(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to leave idle state\n");
goto out;
}
}
if (changed & IEEE80211_CONF_CHANGE_PS) {
if (hw->conf.flags & IEEE80211_CONF_PS) {
rtwdev->ps_enabled = true;
} else {
rtwdev->ps_enabled = false;
rtw_leave_lps(rtwdev);
}
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
rtw_set_channel(rtwdev);
if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
(hw->conf.flags & IEEE80211_CONF_IDLE))
rtw_enter_ips(rtwdev);
out:
mutex_unlock(&rtwdev->mutex);
return ret;
}
static const struct rtw_vif_port rtw_vif_port[] = {
[0] = {
.mac_addr = {.addr = 0x0610},
.bssid = {.addr = 0x0618},
.net_type = {.addr = 0x0100, .mask = 0x30000},
.aid = {.addr = 0x06a8, .mask = 0x7ff},
.bcn_ctrl = {.addr = 0x0550, .mask = 0xff},
},
[1] = {
.mac_addr = {.addr = 0x0700},
.bssid = {.addr = 0x0708},
.net_type = {.addr = 0x0100, .mask = 0xc0000},
.aid = {.addr = 0x0710, .mask = 0x7ff},
.bcn_ctrl = {.addr = 0x0551, .mask = 0xff},
},
[2] = {
.mac_addr = {.addr = 0x1620},
.bssid = {.addr = 0x1628},
.net_type = {.addr = 0x1100, .mask = 0x3},
.aid = {.addr = 0x1600, .mask = 0x7ff},
.bcn_ctrl = {.addr = 0x0578, .mask = 0xff},
},
[3] = {
.mac_addr = {.addr = 0x1630},
.bssid = {.addr = 0x1638},
.net_type = {.addr = 0x1100, .mask = 0xc},
.aid = {.addr = 0x1604, .mask = 0x7ff},
.bcn_ctrl = {.addr = 0x0579, .mask = 0xff},
},
[4] = {
.mac_addr = {.addr = 0x1640},
.bssid = {.addr = 0x1648},
.net_type = {.addr = 0x1100, .mask = 0x30},
.aid = {.addr = 0x1608, .mask = 0x7ff},
.bcn_ctrl = {.addr = 0x057a, .mask = 0xff},
},
};
static int rtw_ops_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
enum rtw_net_type net_type;
u32 config = 0;
u8 port = 0;
u8 bcn_ctrl = 0;
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER))
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
rtwvif->port = port;
rtwvif->stats.tx_unicast = 0;
rtwvif->stats.rx_unicast = 0;
rtwvif->stats.tx_cnt = 0;
rtwvif->stats.rx_cnt = 0;
rtwvif->scan_req = NULL;
memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee));
rtwvif->conf = &rtw_vif_port[port];
rtw_txq_init(rtwdev, vif->txq);
INIT_LIST_HEAD(&rtwvif->rsvd_page_list);
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
rtw_add_rsvd_page_bcn(rtwdev, rtwvif);
net_type = RTW_NET_AP_MODE;
bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
break;
case NL80211_IFTYPE_ADHOC:
rtw_add_rsvd_page_bcn(rtwdev, rtwvif);
net_type = RTW_NET_AD_HOC;
bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
break;
case NL80211_IFTYPE_STATION:
rtw_add_rsvd_page_sta(rtwdev, rtwvif);
net_type = RTW_NET_NO_LINK;
bcn_ctrl = BIT_EN_BCN_FUNCTION;
break;
default:
WARN_ON(1);
mutex_unlock(&rtwdev->mutex);
return -EINVAL;
}
ether_addr_copy(rtwvif->mac_addr, vif->addr);
config |= PORT_SET_MAC_ADDR;
rtwvif->net_type = net_type;
config |= PORT_SET_NET_TYPE;
rtwvif->bcn_ctrl = bcn_ctrl;
config |= PORT_SET_BCN_CTRL;
rtw_vif_port_config(rtwdev, rtwvif, config);
mutex_unlock(&rtwdev->mutex);
#if defined(__linux__)
rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
#elif defined(__FreeBSD__)
rtw_info(rtwdev, "start vif %6D on port %d\n", vif->addr, ":", rtwvif->port);
#endif
return 0;
}
static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
u32 config = 0;
#if defined(__linux__)
rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port);
#elif defined(__FreeBSD__)
rtw_info(rtwdev, "stop vif %6D on port %d\n", vif->addr, ":", rtwvif->port);
#endif
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
rtw_txq_cleanup(rtwdev, vif->txq);
rtw_remove_rsvd_page(rtwdev, rtwvif);
eth_zero_addr(rtwvif->mac_addr);
config |= PORT_SET_MAC_ADDR;
rtwvif->net_type = RTW_NET_NO_LINK;
config |= PORT_SET_NET_TYPE;
rtwvif->bcn_ctrl = 0;
config |= PORT_SET_BCN_CTRL;
rtw_vif_port_config(rtwdev, rtwvif, config);
mutex_unlock(&rtwdev->mutex);
}
static int rtw_ops_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype type, bool p2p)
{
struct rtw_dev *rtwdev = hw->priv;
#if defined(__linux__)
rtw_info(rtwdev, "change vif %pM (%d)->(%d), p2p (%d)->(%d)\n",
vif->addr, vif->type, type, vif->p2p, p2p);
#elif defined(__FreeBSD__)
rtw_info(rtwdev, "change vif %6D (%d)->(%d), p2p (%d)->(%d)\n",
vif->addr, ":", vif->type, type, vif->p2p, p2p);
#endif
rtw_ops_remove_interface(hw, vif);
vif->type = type;
vif->p2p = p2p;
return rtw_ops_add_interface(hw, vif);
}
static void rtw_ops_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *new_flags,
u64 multicast)
{
struct rtw_dev *rtwdev = hw->priv;
*new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL |
FIF_BCN_PRBRESP_PROMISC;
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
if (changed_flags & FIF_ALLMULTI) {
if (*new_flags & FIF_ALLMULTI)
rtwdev->hal.rcr |= BIT_AM | BIT_AB;
else
rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB);
}
if (changed_flags & FIF_FCSFAIL) {
if (*new_flags & FIF_FCSFAIL)
rtwdev->hal.rcr |= BIT_ACRC32;
else
rtwdev->hal.rcr &= ~(BIT_ACRC32);
}
if (changed_flags & FIF_OTHER_BSS) {
if (*new_flags & FIF_OTHER_BSS)
rtwdev->hal.rcr |= BIT_AAP;
else
rtwdev->hal.rcr &= ~(BIT_AAP);
}
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
rtwdev->hal.rcr &= ~(BIT_CBSSID_BCN | BIT_CBSSID_DATA);
else
rtwdev->hal.rcr |= BIT_CBSSID_BCN;
}
rtw_dbg(rtwdev, RTW_DBG_RX,
"config rx filter, changed=0x%08x, new=0x%08x, rcr=0x%08x\n",
changed_flags, *new_flags, rtwdev->hal.rcr);
rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);
mutex_unlock(&rtwdev->mutex);
}
/* Only have one group of EDCA parameters now */
static const u32 ac_to_edca_param[IEEE80211_NUM_ACS] = {
[IEEE80211_AC_VO] = REG_EDCA_VO_PARAM,
[IEEE80211_AC_VI] = REG_EDCA_VI_PARAM,
[IEEE80211_AC_BE] = REG_EDCA_BE_PARAM,
[IEEE80211_AC_BK] = REG_EDCA_BK_PARAM,
};
static u8 rtw_aifsn_to_aifs(struct rtw_dev *rtwdev,
struct rtw_vif *rtwvif, u8 aifsn)
{
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
u8 slot_time;
u8 sifs;
slot_time = vif->bss_conf.use_short_slot ? 9 : 20;
sifs = rtwdev->hal.current_band_type == RTW_BAND_5G ? 16 : 10;
return aifsn * slot_time + sifs;
}
static void __rtw_conf_tx(struct rtw_dev *rtwdev,
struct rtw_vif *rtwvif, u16 ac)
{
struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac];
u32 edca_param = ac_to_edca_param[ac];
u8 ecw_max, ecw_min;
u8 aifs;
/* 2^ecw - 1 = cw; ecw = log2(cw + 1) */
ecw_max = ilog2(params->cw_max + 1);
ecw_min = ilog2(params->cw_min + 1);
aifs = rtw_aifsn_to_aifs(rtwdev, rtwvif, params->aifs);
rtw_write32_mask(rtwdev, edca_param, BIT_MASK_TXOP_LMT, params->txop);
rtw_write32_mask(rtwdev, edca_param, BIT_MASK_CWMAX, ecw_max);
rtw_write32_mask(rtwdev, edca_param, BIT_MASK_CWMIN, ecw_min);
rtw_write32_mask(rtwdev, edca_param, BIT_MASK_AIFS, aifs);
}
static void rtw_conf_tx(struct rtw_dev *rtwdev,
struct rtw_vif *rtwvif)
{
u16 ac;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
__rtw_conf_tx(rtwdev, rtwvif, ac);
}
static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf,
u32 changed)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
u32 config = 0;
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
if (changed & BSS_CHANGED_ASSOC) {
rtw_vif_assoc_changed(rtwvif, conf);
if (conf->assoc) {
rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH);
rtw_fw_download_rsvd_page(rtwdev);
rtw_send_rsvd_page_h2c(rtwdev);
rtw_coex_media_status_notify(rtwdev, conf->assoc);
if (rtw_bf_support)
rtw_bf_assoc(rtwdev, vif, conf);
rtw_store_op_chan(rtwdev);
} else {
rtw_leave_lps(rtwdev);
rtw_bf_disassoc(rtwdev, vif, conf);
/* Abort ongoing scan if cancel_scan isn't issued
* when disconnected by peer
*/
if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
rtw_hw_scan_abort(rtwdev, vif);
}
config |= PORT_SET_NET_TYPE;
config |= PORT_SET_AID;
}
if (changed & BSS_CHANGED_BSSID) {
ether_addr_copy(rtwvif->bssid, conf->bssid);
config |= PORT_SET_BSSID;
}
if (changed & BSS_CHANGED_BEACON_INT) {
if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION)
coex_stat->wl_beacon_interval = conf->beacon_int;
}
if (changed & BSS_CHANGED_BEACON)
rtw_fw_download_rsvd_page(rtwdev);
if (changed & BSS_CHANGED_BEACON_ENABLED) {
if (conf->enable_beacon)
rtw_write32_set(rtwdev, REG_FWHW_TXQ_CTRL,
BIT_EN_BCNQ_DL);
else
rtw_write32_clr(rtwdev, REG_FWHW_TXQ_CTRL,
BIT_EN_BCNQ_DL);
}
if (changed & BSS_CHANGED_CQM)
rtw_fw_beacon_filter_config(rtwdev, true, vif);
if (changed & BSS_CHANGED_MU_GROUPS)
rtw_chip_set_gid_table(rtwdev, vif, conf);
if (changed & BSS_CHANGED_ERP_SLOT)
rtw_conf_tx(rtwdev, rtwvif);
rtw_vif_port_config(rtwdev, rtwvif, config);
mutex_unlock(&rtwdev->mutex);
}
static int rtw_ops_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
rtwvif->tx_params[ac] = *params;
__rtw_conf_tx(rtwdev, rtwvif, ac);
mutex_unlock(&rtwdev->mutex);
return 0;
}
static int rtw_ops_sta_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct rtw_dev *rtwdev = hw->priv;
int ret = 0;
mutex_lock(&rtwdev->mutex);
ret = rtw_sta_add(rtwdev, sta, vif);
mutex_unlock(&rtwdev->mutex);
return ret;
}
static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct rtw_dev *rtwdev = hw->priv;
rtw_fw_beacon_filter_config(rtwdev, false, vif);
mutex_lock(&rtwdev->mutex);
rtw_sta_remove(rtwdev, sta, true);
mutex_unlock(&rtwdev->mutex);
return 0;
}
static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_sec_desc *sec = &rtwdev->sec;
u8 hw_key_type;
u8 hw_key_idx;
int ret = 0;
switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
hw_key_type = RTW_CAM_WEP40;
break;
case WLAN_CIPHER_SUITE_WEP104:
hw_key_type = RTW_CAM_WEP104;
break;
case WLAN_CIPHER_SUITE_TKIP:
hw_key_type = RTW_CAM_TKIP;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
break;
case WLAN_CIPHER_SUITE_CCMP:
hw_key_type = RTW_CAM_AES;
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
/* suppress error messages */
return -EOPNOTSUPP;
default:
return -ENOTSUPP;
}
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
hw_key_idx = rtw_sec_get_free_cam(sec);
} else {
/* multiple interfaces? */
hw_key_idx = key->keyidx;
}
if (hw_key_idx > sec->total_cam_num) {
ret = -ENOSPC;
goto out;
}
switch (cmd) {
case SET_KEY:
/* need sw generated IV */
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
key->hw_key_idx = hw_key_idx;
rtw_sec_write_cam(rtwdev, sec, sta, key,
hw_key_type, hw_key_idx);
break;
case DISABLE_KEY:
rtw_hci_flush_all_queues(rtwdev, false);
rtw_mac_flush_all_queues(rtwdev, false);
rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx);
break;
}
/* download new cam settings for PG to backup */
if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG)
rtw_fw_download_rsvd_page(rtwdev);
out:
mutex_unlock(&rtwdev->mutex);
return ret;
}
static int rtw_ops_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params)
{
struct ieee80211_sta *sta = params->sta;
u16 tid = params->tid;
struct ieee80211_txq *txq = sta->txq[tid];
struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv;
switch (params->action) {
case IEEE80211_AMPDU_TX_START:
return IEEE80211_AMPDU_TX_START_IMMEDIATE;
case IEEE80211_AMPDU_TX_STOP_CONT:
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
clear_bit(RTW_TXQ_AMPDU, &rtwtxq->flags);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
set_bit(RTW_TXQ_AMPDU, &rtwtxq->flags);
break;
case IEEE80211_AMPDU_RX_START:
case IEEE80211_AMPDU_RX_STOP:
break;
default:
WARN_ON(1);
return -ENOTSUPP;
}
return 0;
}
static bool rtw_ops_can_aggregate_in_amsdu(struct ieee80211_hw *hw,
struct sk_buff *head,
struct sk_buff *skb)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_hal *hal = &rtwdev->hal;
/* we don't want to enable TX AMSDU on 2.4G */
if (hal->current_band_type == RTW_BAND_2G)
return false;
return true;
}
static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const u8 *mac_addr)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
mutex_lock(&rtwdev->mutex);
rtw_core_scan_start(rtwdev, rtwvif, mac_addr, false);
mutex_unlock(&rtwdev->mutex);
}
static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rtw_dev *rtwdev = hw->priv;
mutex_lock(&rtwdev->mutex);
rtw_core_scan_complete(rtwdev, vif);
mutex_unlock(&rtwdev->mutex);
}
static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_prep_tx_info *info)
{
struct rtw_dev *rtwdev = hw->priv;
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START);
rtw_chip_prepare_tx(rtwdev);
mutex_unlock(&rtwdev->mutex);
}
static int rtw_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
struct rtw_dev *rtwdev = hw->priv;
mutex_lock(&rtwdev->mutex);
rtwdev->rts_threshold = value;
mutex_unlock(&rtwdev->mutex);
return 0;
}
static void rtw_ops_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct station_info *sinfo)
{
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
sinfo->txrate = si->ra_report.txrate;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
static void rtw_ops_flush(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct rtw_dev *rtwdev = hw->priv;
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
rtw_hci_flush_queues(rtwdev, queues, drop);
rtw_mac_flush_queues(rtwdev, queues, drop);
mutex_unlock(&rtwdev->mutex);
}
struct rtw_iter_bitrate_mask_data {
struct rtw_dev *rtwdev;
struct ieee80211_vif *vif;
const struct cfg80211_bitrate_mask *mask;
};
static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw_iter_bitrate_mask_data *br_data = data;
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
if (si->vif != br_data->vif)
return;
/* free previous mask setting */
kfree(si->mask);
si->mask = kmemdup(br_data->mask, sizeof(struct cfg80211_bitrate_mask),
GFP_ATOMIC);
if (!si->mask) {
si->use_cfg_mask = false;
return;
}
si->use_cfg_mask = true;
rtw_update_sta_info(br_data->rtwdev, si);
}
static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask)
{
struct rtw_iter_bitrate_mask_data br_data;
br_data.rtwdev = rtwdev;
br_data.vif = vif;
br_data.mask = mask;
rtw_iterate_stas_atomic(rtwdev, rtw_ra_mask_info_update_iter, &br_data);
}
static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask)
{
struct rtw_dev *rtwdev = hw->priv;
rtw_ra_mask_info_update(rtwdev, vif, mask);
return 0;
}
static int rtw_ops_set_antenna(struct ieee80211_hw *hw,
u32 tx_antenna,
u32 rx_antenna)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_chip_info *chip = rtwdev->chip;
int ret;
if (!chip->ops->set_antenna)
return -EOPNOTSUPP;
mutex_lock(&rtwdev->mutex);
ret = chip->ops->set_antenna(rtwdev, tx_antenna, rx_antenna);
mutex_unlock(&rtwdev->mutex);
return ret;
}
static int rtw_ops_get_antenna(struct ieee80211_hw *hw,
u32 *tx_antenna,
u32 *rx_antenna)
{
struct rtw_dev *rtwdev = hw->priv;
struct rtw_hal *hal = &rtwdev->hal;
*tx_antenna = hal->antenna_tx;
*rx_antenna = hal->antenna_rx;
return 0;
}
#ifdef CONFIG_PM
static int rtw_ops_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
{
struct rtw_dev *rtwdev = hw->priv;
int ret;
mutex_lock(&rtwdev->mutex);
ret = rtw_wow_suspend(rtwdev, wowlan);
if (ret)
rtw_err(rtwdev, "failed to suspend for wow %d\n", ret);
mutex_unlock(&rtwdev->mutex);
return ret ? 1 : 0;
}
static int rtw_ops_resume(struct ieee80211_hw *hw)
{
struct rtw_dev *rtwdev = hw->priv;
int ret;
mutex_lock(&rtwdev->mutex);
ret = rtw_wow_resume(rtwdev);
if (ret)
rtw_err(rtwdev, "failed to resume for wow %d\n", ret);
mutex_unlock(&rtwdev->mutex);
return ret ? 1 : 0;
}
static void rtw_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled)
{
struct rtw_dev *rtwdev = hw->priv;
device_set_wakeup_enable(rtwdev->dev, enabled);
}
#endif
static void rtw_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type)
{
struct rtw_dev *rtwdev = hw->priv;
mutex_lock(&rtwdev->mutex);
if (reconfig_type == IEEE80211_RECONFIG_TYPE_RESTART)
clear_bit(RTW_FLAG_RESTARTING, rtwdev->flags);
mutex_unlock(&rtwdev->mutex);
}
static int rtw_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_scan_request *req)
{
struct rtw_dev *rtwdev = hw->priv;
int ret;
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD))
return 1;
if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
return -EBUSY;
mutex_lock(&rtwdev->mutex);
rtw_hw_scan_start(rtwdev, vif, req);
ret = rtw_hw_scan_offload(rtwdev, vif, true);
if (ret) {
rtw_hw_scan_abort(rtwdev, vif);
rtw_err(rtwdev, "HW scan failed with status: %d\n", ret);
}
mutex_unlock(&rtwdev->mutex);
return ret;
}
static void rtw_ops_cancel_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rtw_dev *rtwdev = hw->priv;
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD))
return;
if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
return;
mutex_lock(&rtwdev->mutex);
rtw_hw_scan_abort(rtwdev, vif);
mutex_unlock(&rtwdev->mutex);
}
static int rtw_ops_set_sar_specs(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar)
{
struct rtw_dev *rtwdev = hw->priv;
rtw_set_sar_specs(rtwdev, sar);
return 0;
}
const struct ieee80211_ops rtw_ops = {
.tx = rtw_ops_tx,
.wake_tx_queue = rtw_ops_wake_tx_queue,
.start = rtw_ops_start,
.stop = rtw_ops_stop,
.config = rtw_ops_config,
.add_interface = rtw_ops_add_interface,
.remove_interface = rtw_ops_remove_interface,
.change_interface = rtw_ops_change_interface,
.configure_filter = rtw_ops_configure_filter,
.bss_info_changed = rtw_ops_bss_info_changed,
.conf_tx = rtw_ops_conf_tx,
.sta_add = rtw_ops_sta_add,
.sta_remove = rtw_ops_sta_remove,
.set_key = rtw_ops_set_key,
.ampdu_action = rtw_ops_ampdu_action,
.can_aggregate_in_amsdu = rtw_ops_can_aggregate_in_amsdu,
.sw_scan_start = rtw_ops_sw_scan_start,
.sw_scan_complete = rtw_ops_sw_scan_complete,
.mgd_prepare_tx = rtw_ops_mgd_prepare_tx,
.set_rts_threshold = rtw_ops_set_rts_threshold,
.sta_statistics = rtw_ops_sta_statistics,
.flush = rtw_ops_flush,
.set_bitrate_mask = rtw_ops_set_bitrate_mask,
.set_antenna = rtw_ops_set_antenna,
.get_antenna = rtw_ops_get_antenna,
.reconfig_complete = rtw_reconfig_complete,
.hw_scan = rtw_ops_hw_scan,
.cancel_hw_scan = rtw_ops_cancel_hw_scan,
.set_sar_specs = rtw_ops_set_sar_specs,
#ifdef CONFIG_PM
.suspend = rtw_ops_suspend,
.resume = rtw_ops_resume,
.set_wakeup = rtw_ops_set_wakeup,
#endif
};
EXPORT_SYMBOL(rtw_ops);

2122
sys/contrib/dev/rtw88/main.c Normal file

File diff suppressed because it is too large Load Diff

2139
sys/contrib/dev/rtw88/main.h Normal file

File diff suppressed because it is too large Load Diff

1939
sys/contrib/dev/rtw88/pci.c Normal file

File diff suppressed because it is too large Load Diff

279
sys/contrib/dev/rtw88/pci.h Normal file
View File

@ -0,0 +1,279 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTK_PCI_H_
#define __RTK_PCI_H_
#include "main.h"
#define RTK_DEFAULT_TX_DESC_NUM 128
#define RTK_BEQ_TX_DESC_NUM 256
#define RTK_MAX_RX_DESC_NUM 512
/* 11K + rx desc size */
#define RTK_PCI_RX_BUF_SIZE (11454 + 24)
#define RTK_PCI_CTRL 0x300
#define BIT_RST_TRXDMA_INTF BIT(20)
#define BIT_RX_TAG_EN BIT(15)
#define REG_DBI_WDATA_V1 0x03E8
#define REG_DBI_RDATA_V1 0x03EC
#define REG_DBI_FLAG_V1 0x03F0
#define BIT_DBI_RFLAG BIT(17)
#define BIT_DBI_WFLAG BIT(16)
#define BITS_DBI_WREN GENMASK(15, 12)
#define BITS_DBI_ADDR_MASK GENMASK(11, 2)
#define REG_MDIO_V1 0x03F4
#define REG_PCIE_MIX_CFG 0x03F8
#define BITS_MDIO_ADDR_MASK GENMASK(4, 0)
#define BIT_MDIO_WFLAG_V1 BIT(5)
#define RTW_PCI_MDIO_PG_SZ BIT(5)
#define RTW_PCI_MDIO_PG_OFFS_G1 0
#define RTW_PCI_MDIO_PG_OFFS_G2 2
#define RTW_PCI_WR_RETRY_CNT 20
#define RTK_PCIE_LINK_CFG 0x0719
#define BIT_CLKREQ_SW_EN BIT(4)
#define BIT_L1_SW_EN BIT(3)
#define BIT_CLKREQ_N_PAD BIT(0)
#define RTK_PCIE_CLKDLY_CTRL 0x0725
#define BIT_PCI_BCNQ_FLAG BIT(4)
#define RTK_PCI_TXBD_DESA_BCNQ 0x308
#define RTK_PCI_TXBD_DESA_H2CQ 0x1320
#define RTK_PCI_TXBD_DESA_MGMTQ 0x310
#define RTK_PCI_TXBD_DESA_BKQ 0x330
#define RTK_PCI_TXBD_DESA_BEQ 0x328
#define RTK_PCI_TXBD_DESA_VIQ 0x320
#define RTK_PCI_TXBD_DESA_VOQ 0x318
#define RTK_PCI_TXBD_DESA_HI0Q 0x340
#define RTK_PCI_RXBD_DESA_MPDUQ 0x338
#define TRX_BD_IDX_MASK GENMASK(11, 0)
#define TRX_BD_HW_IDX_MASK GENMASK(27, 16)
/* BCNQ is specialized for rsvd page, does not need to specify a number */
#define RTK_PCI_TXBD_NUM_H2CQ 0x1328
#define RTK_PCI_TXBD_NUM_MGMTQ 0x380
#define RTK_PCI_TXBD_NUM_BKQ 0x38A
#define RTK_PCI_TXBD_NUM_BEQ 0x388
#define RTK_PCI_TXBD_NUM_VIQ 0x386
#define RTK_PCI_TXBD_NUM_VOQ 0x384
#define RTK_PCI_TXBD_NUM_HI0Q 0x38C
#define RTK_PCI_RXBD_NUM_MPDUQ 0x382
#define RTK_PCI_TXBD_IDX_H2CQ 0x132C
#define RTK_PCI_TXBD_IDX_MGMTQ 0x3B0
#define RTK_PCI_TXBD_IDX_BKQ 0x3AC
#define RTK_PCI_TXBD_IDX_BEQ 0x3A8
#define RTK_PCI_TXBD_IDX_VIQ 0x3A4
#define RTK_PCI_TXBD_IDX_VOQ 0x3A0
#define RTK_PCI_TXBD_IDX_HI0Q 0x3B8
#define RTK_PCI_RXBD_IDX_MPDUQ 0x3B4
#define RTK_PCI_TXBD_RWPTR_CLR 0x39C
#define RTK_PCI_TXBD_H2CQ_CSR 0x1330
#define BIT_CLR_H2CQ_HOST_IDX BIT(16)
#define BIT_CLR_H2CQ_HW_IDX BIT(8)
#define RTK_PCI_HIMR0 0x0B0
#define RTK_PCI_HISR0 0x0B4
#define RTK_PCI_HIMR1 0x0B8
#define RTK_PCI_HISR1 0x0BC
#define RTK_PCI_HIMR2 0x10B0
#define RTK_PCI_HISR2 0x10B4
#define RTK_PCI_HIMR3 0x10B8
#define RTK_PCI_HISR3 0x10BC
/* IMR 0 */
#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 1 */
#define IMR_TXFIFO_TH_INT BIT(30)
#define IMR_BTON_STS_UPDATE BIT(29)
#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 BIT(5)
#define IMR_PS_TIMER_C BIT(4)
#define IMR_PS_TIMER_B BIT(3)
#define IMR_PS_TIMER_A BIT(2)
#define IMR_CPUMGQ_TX_TIMER BIT(1)
/* IMR 3 */
#define IMR_H2CDOK BIT(16)
enum rtw_pci_flags {
RTW_PCI_FLAG_NAPI_RUNNING,
NUM_OF_RTW_PCI_FLAGS,
};
/* one element is reserved to know if the ring is closed */
static inline int avail_desc(u32 wp, u32 rp, u32 len)
{
if (rp > wp)
return rp - wp - 1;
else
return len - wp + rp - 1;
}
#define RTK_PCI_TXBD_OWN_OFFSET 15
#define RTK_PCI_TXBD_BCN_WORK 0x383
struct rtw_pci_tx_buffer_desc {
__le16 buf_size;
__le16 psb_len;
__le32 dma;
};
struct rtw_pci_tx_data {
dma_addr_t dma;
u8 sn;
};
struct rtw_pci_ring {
u8 *head;
dma_addr_t dma;
u8 desc_size;
u32 len;
u32 wp;
u32 rp;
};
struct rtw_pci_tx_ring {
struct rtw_pci_ring r;
struct sk_buff_head queue;
bool queue_stopped;
};
struct rtw_pci_rx_buffer_desc {
__le16 buf_size;
__le16 total_pkt_size;
__le32 dma;
};
struct rtw_pci_rx_ring {
struct rtw_pci_ring r;
struct sk_buff *buf[RTK_MAX_RX_DESC_NUM];
};
#define RX_TAG_MAX 8192
struct rtw_pci {
struct pci_dev *pdev;
/* Used for PCI interrupt. */
spinlock_t hwirq_lock;
/* Used for PCI TX ring/queueing, and enable INT. */
spinlock_t irq_lock;
u32 irq_mask[4];
bool irq_enabled;
bool running;
/* napi structure */
struct net_device netdev;
struct napi_struct napi;
u16 rx_tag;
DECLARE_BITMAP(tx_queued, RTK_MAX_TX_QUEUE_NUM);
struct rtw_pci_tx_ring tx_rings[RTK_MAX_TX_QUEUE_NUM];
struct rtw_pci_rx_ring rx_rings[RTK_MAX_RX_QUEUE_NUM];
u16 link_ctrl;
atomic_t link_usage;
bool rx_no_aspm;
DECLARE_BITMAP(flags, NUM_OF_RTW_PCI_FLAGS);
void __iomem *mmap;
};
extern const struct dev_pm_ops rtw_pm_ops;
int rtw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
void rtw_pci_remove(struct pci_dev *pdev);
void rtw_pci_shutdown(struct pci_dev *pdev);
static inline u32 max_num_of_tx_queue(u8 queue)
{
u32 max_num;
switch (queue) {
case RTW_TX_QUEUE_BE:
max_num = RTK_BEQ_TX_DESC_NUM;
break;
case RTW_TX_QUEUE_BCN:
max_num = 1;
break;
default:
max_num = RTK_DEFAULT_TX_DESC_NUM;
break;
}
return max_num;
}
static inline struct
rtw_pci_tx_data *rtw_pci_get_tx_data(struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
BUILD_BUG_ON(sizeof(struct rtw_pci_tx_data) >
sizeof(info->status.status_driver_data));
return (struct rtw_pci_tx_data *)info->status.status_driver_data;
}
static inline
struct rtw_pci_tx_buffer_desc *get_tx_buffer_desc(struct rtw_pci_tx_ring *ring,
u32 size)
{
u8 *buf_desc;
buf_desc = ring->r.head + ring->r.wp * size;
return (struct rtw_pci_tx_buffer_desc *)buf_desc;
}
#endif

2548
sys/contrib/dev/rtw88/phy.c Normal file

File diff suppressed because it is too large Load Diff

198
sys/contrib/dev/rtw88/phy.h Normal file
View File

@ -0,0 +1,198 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_PHY_H_
#define __RTW_PHY_H_
#include "debug.h"
extern u8 rtw_cck_rates[];
extern u8 rtw_ofdm_rates[];
extern u8 rtw_ht_1s_rates[];
extern u8 rtw_ht_2s_rates[];
extern u8 rtw_vht_1s_rates[];
extern u8 rtw_vht_2s_rates[];
extern u8 *rtw_rate_section[];
extern u8 rtw_rate_size[];
void rtw_phy_init(struct rtw_dev *rtwdev);
void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev);
u8 rtw_phy_rf_power_2_rssi(s8 *rf_power, u8 path_num);
u32 rtw_phy_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
u32 addr, u32 mask);
u32 rtw_phy_read_rf_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
u32 addr, u32 mask);
bool rtw_phy_write_rf_reg_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
u32 addr, u32 mask, u32 data);
bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
u32 addr, u32 mask, u32 data);
bool rtw_phy_write_rf_reg_mix(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
u32 addr, u32 mask, u32 data);
void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg);
void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl);
void rtw_parse_tbl_bb_pg(struct rtw_dev *rtwdev, const struct rtw_table *tbl);
void rtw_parse_tbl_txpwr_lmt(struct rtw_dev *rtwdev, const struct rtw_table *tbl);
void rtw_phy_cfg_mac(struct rtw_dev *rtwdev, const struct rtw_table *tbl,
u32 addr, u32 data);
void rtw_phy_cfg_agc(struct rtw_dev *rtwdev, const struct rtw_table *tbl,
u32 addr, u32 data);
void rtw_phy_cfg_bb(struct rtw_dev *rtwdev, const struct rtw_table *tbl,
u32 addr, u32 data);
void rtw_phy_cfg_rf(struct rtw_dev *rtwdev, const struct rtw_table *tbl,
u32 addr, u32 data);
void rtw_phy_init_tx_power(struct rtw_dev *rtwdev);
void rtw_phy_load_tables(struct rtw_dev *rtwdev);
u8 rtw_phy_get_tx_power_index(struct rtw_dev *rtwdev, u8 rf_path, u8 rate,
enum rtw_bandwidth bw, u8 channel, u8 regd);
void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel);
void rtw_phy_tx_power_by_rate_config(struct rtw_hal *hal);
void rtw_phy_tx_power_limit_config(struct rtw_hal *hal);
void rtw_phy_pwrtrack_avg(struct rtw_dev *rtwdev, u8 thermal, u8 path);
bool rtw_phy_pwrtrack_thermal_changed(struct rtw_dev *rtwdev, u8 thermal,
u8 path);
u8 rtw_phy_pwrtrack_get_delta(struct rtw_dev *rtwdev, u8 path);
s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev,
struct rtw_swing_table *swing_table,
u8 tbl_path, u8 therm_path, u8 delta);
bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev);
bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev);
void rtw_phy_config_swing_table(struct rtw_dev *rtwdev,
struct rtw_swing_table *swing_table);
void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l);
void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev);
void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev,
struct rtw_rx_pkt_stat *pkt_stat);
void rtw_phy_tx_path_diversity(struct rtw_dev *rtwdev);
struct rtw_txpwr_lmt_cfg_pair {
u8 regd;
u8 band;
u8 bw;
u8 rs;
u8 ch;
s8 txpwr_lmt;
};
struct rtw_phy_pg_cfg_pair {
u32 band;
u32 rf_path;
u32 tx_num;
u32 addr;
u32 bitmask;
u32 data;
};
#define RTW_DECL_TABLE_PHY_COND_CORE(name, cfg, path) \
const struct rtw_table name ## _tbl = { \
.data = name, \
.size = ARRAY_SIZE(name), \
.parse = rtw_parse_tbl_phy_cond, \
.do_cfg = cfg, \
.rf_path = path, \
}
#define RTW_DECL_TABLE_PHY_COND(name, cfg) \
RTW_DECL_TABLE_PHY_COND_CORE(name, cfg, 0)
#define RTW_DECL_TABLE_RF_RADIO(name, path) \
RTW_DECL_TABLE_PHY_COND_CORE(name, rtw_phy_cfg_rf, RF_PATH_ ## path)
#define RTW_DECL_TABLE_BB_PG(name) \
const struct rtw_table name ## _tbl = { \
.data = name, \
.size = ARRAY_SIZE(name), \
.parse = rtw_parse_tbl_bb_pg, \
}
#define RTW_DECL_TABLE_TXPWR_LMT(name) \
const struct rtw_table name ## _tbl = { \
.data = name, \
.size = ARRAY_SIZE(name), \
.parse = rtw_parse_tbl_txpwr_lmt, \
}
static inline const struct rtw_rfe_def *rtw_get_rfe_def(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_efuse *efuse = &rtwdev->efuse;
const struct rtw_rfe_def *rfe_def = NULL;
if (chip->rfe_defs_size == 0)
return NULL;
if (efuse->rfe_option < chip->rfe_defs_size)
rfe_def = &chip->rfe_defs[efuse->rfe_option];
rtw_dbg(rtwdev, RTW_DBG_PHY, "use rfe_def[%d]\n", efuse->rfe_option);
return rfe_def;
}
static inline int rtw_check_supported_rfe(struct rtw_dev *rtwdev)
{
const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev);
if (!rfe_def || !rfe_def->phy_pg_tbl || !rfe_def->txpwr_lmt_tbl) {
rtw_err(rtwdev, "rfe %d isn't supported\n",
rtwdev->efuse.rfe_option);
return -ENODEV;
}
return 0;
}
void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi);
struct rtw_power_params {
u8 pwr_base;
s8 pwr_offset;
s8 pwr_limit;
s8 pwr_remnant;
s8 pwr_sar;
};
void
rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path,
u8 rate, u8 bw, u8 ch, u8 regd,
struct rtw_power_params *pwr_param);
enum rtw_phy_cck_pd_lv {
CCK_PD_LV0,
CCK_PD_LV1,
CCK_PD_LV2,
CCK_PD_LV3,
CCK_PD_LV4,
CCK_PD_LV_MAX,
};
#define MASKBYTE0 0xff
#define MASKBYTE1 0xff00
#define MASKBYTE2 0xff0000
#define MASKBYTE3 0xff000000
#define MASKHWORD 0xffff0000
#define MASKLWORD 0x0000ffff
#define MASKDWORD 0xffffffff
#define RFREG_MASK 0xfffff
#define MASK7BITS 0x7f
#define MASK12BITS 0xfff
#define MASKH4BITS 0xf0000000
#define MASK20BITS 0xfffff
#define MASK24BITS 0xffffff
#define MASKH3BYTES 0xffffff00
#define MASKL3BYTES 0x00ffffff
#define MASKBYTE2HIGHNIBBLE 0x00f00000
#define MASKBYTE3LOWNIBBLE 0x0f000000
#define MASKL3BYTES 0x00ffffff
#define CCK_FA_AVG_RESET 0xffffffff
#define LSSI_READ_ADDR_MASK 0x7f800000
#define LSSI_READ_EDGE_MASK 0x80000000
#define LSSI_READ_DATA_MASK 0xfffff
#define RRSR_RATE_ORDER_MAX 0xfffff
#define RRSR_RATE_ORDER_CCK_LEN 4
#endif

298
sys/contrib/dev/rtw88/ps.c Normal file
View File

@ -0,0 +1,298 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "reg.h"
#include "fw.h"
#include "ps.h"
#include "mac.h"
#include "coex.h"
#include "debug.h"
static int rtw_ips_pwr_up(struct rtw_dev *rtwdev)
{
int ret;
ret = rtw_core_start(rtwdev);
if (ret)
rtw_err(rtwdev, "leave idle state failed\n");
rtw_set_channel(rtwdev);
clear_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
return ret;
}
int rtw_enter_ips(struct rtw_dev *rtwdev)
{
set_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
rtw_core_stop(rtwdev);
rtw_hci_link_ps(rtwdev, true);
return 0;
}
static void rtw_restore_port_cfg_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct rtw_dev *rtwdev = data;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
u32 config = ~0;
rtw_vif_port_config(rtwdev, rtwvif, config);
}
int rtw_leave_ips(struct rtw_dev *rtwdev)
{
int ret;
rtw_hci_link_ps(rtwdev, false);
ret = rtw_ips_pwr_up(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to leave ips state\n");
return ret;
}
rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
return 0;
}
void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter)
{
u8 request, confirm, polling;
int ret;
request = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
confirm = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr);
/* toggle to request power mode, others remain 0 */
request ^= request | BIT_RPWM_TOGGLE;
if (enter) {
request |= POWER_MODE_LCLK;
if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG)
request |= POWER_MODE_PG;
}
/* Each request require an ack from firmware */
request |= POWER_MODE_ACK;
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE))
request |= POWER_TX_WAKE;
rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, request);
/* Check firmware get the power requset and ack via cpwm register */
ret = read_poll_timeout_atomic(rtw_read8, polling,
(polling ^ confirm) & BIT_RPWM_TOGGLE,
100, 15000, true, rtwdev,
rtwdev->hci.cpwm_addr);
if (ret) {
/* Hit here means that driver failed to get an ack from firmware.
* The reason could be that hardware is locked at Deep sleep,
* so most of the hardware circuits are not working, even
* register read/write; or firmware is locked in some state and
* cannot get the request. It should be treated as fatal error
* and requires an entire analysis about the firmware/hardware.
*/
WARN(1, "firmware failed to ack driver for %s Deep Power mode\n",
enter ? "entering" : "leaving");
}
}
EXPORT_SYMBOL(rtw_power_mode_change);
static void __rtw_leave_lps_deep(struct rtw_dev *rtwdev)
{
rtw_hci_deep_ps(rtwdev, false);
}
static int __rtw_fw_leave_lps_check_reg(struct rtw_dev *rtwdev)
{
int i;
/* Driver needs to wait for firmware to leave LPS state
* successfully. Firmware will send null packet to inform AP,
* and see if AP sends an ACK back, then firmware will restore
* the REG_TCR register.
*
* If driver does not wait for firmware, null packet with
* PS bit could be sent due to incorrect REG_TCR setting.
*
* In our test, 100ms should be enough for firmware to finish
* the flow. If REG_TCR Register is still incorrect after 100ms,
* just modify it directly, and throw a warn message.
*/
for (i = 0 ; i < LEAVE_LPS_TRY_CNT; i++) {
if (rtw_read32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN) == 0)
return 0;
msleep(20);
}
return -EBUSY;
}
static int __rtw_fw_leave_lps_check_c2h(struct rtw_dev *rtwdev)
{
if (wait_for_completion_timeout(&rtwdev->lps_leave_check,
LEAVE_LPS_TIMEOUT))
return 0;
return -EBUSY;
}
static void rtw_fw_leave_lps_check(struct rtw_dev *rtwdev)
{
bool ret = false;
struct rtw_fw_state *fw;
if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
fw = &rtwdev->wow_fw;
else
fw = &rtwdev->fw;
if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H))
ret = __rtw_fw_leave_lps_check_c2h(rtwdev);
else
ret = __rtw_fw_leave_lps_check_reg(rtwdev);
if (ret) {
rtw_write32_clr(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN);
rtw_warn(rtwdev, "firmware failed to leave lps state\n");
}
}
static void rtw_fw_leave_lps_check_prepare(struct rtw_dev *rtwdev)
{
struct rtw_fw_state *fw;
if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
fw = &rtwdev->wow_fw;
else
fw = &rtwdev->fw;
if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H))
reinit_completion(&rtwdev->lps_leave_check);
}
static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
{
struct rtw_lps_conf *conf = &rtwdev->lps_conf;
conf->state = RTW_ALL_ON;
conf->awake_interval = 1;
conf->rlbm = 0;
conf->smart_ps = 0;
rtw_hci_link_ps(rtwdev, false);
rtw_fw_leave_lps_check_prepare(rtwdev);
rtw_fw_set_pwr_mode(rtwdev);
rtw_fw_leave_lps_check(rtwdev);
clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE);
}
enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev)
{
if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
return rtwdev->lps_conf.wow_deep_mode;
else
return rtwdev->lps_conf.deep_mode;
}
static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev)
{
if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_NONE)
return;
if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) {
rtw_dbg(rtwdev, RTW_DBG_PS,
"Should enter LPS before entering deep PS\n");
return;
}
if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG)
rtw_fw_set_pg_info(rtwdev);
rtw_hci_deep_ps(rtwdev, true);
}
static void rtw_enter_lps_core(struct rtw_dev *rtwdev)
{
struct rtw_lps_conf *conf = &rtwdev->lps_conf;
conf->state = RTW_RF_OFF;
conf->awake_interval = 1;
conf->rlbm = 1;
conf->smart_ps = 2;
rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE);
rtw_fw_set_pwr_mode(rtwdev);
rtw_hci_link_ps(rtwdev, true);
set_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
}
static void __rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id)
{
struct rtw_lps_conf *conf = &rtwdev->lps_conf;
if (test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags))
return;
conf->mode = RTW_MODE_LPS;
conf->port_id = port_id;
rtw_enter_lps_core(rtwdev);
}
static void __rtw_leave_lps(struct rtw_dev *rtwdev)
{
struct rtw_lps_conf *conf = &rtwdev->lps_conf;
if (test_and_clear_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) {
rtw_dbg(rtwdev, RTW_DBG_PS,
"Should leave deep PS before leaving LPS\n");
__rtw_leave_lps_deep(rtwdev);
}
if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags))
return;
conf->mode = RTW_MODE_ACTIVE;
rtw_leave_lps_core(rtwdev);
}
void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id)
{
lockdep_assert_held(&rtwdev->mutex);
if (rtwdev->coex.stat.wl_force_lps_ctrl)
return;
__rtw_enter_lps(rtwdev, port_id);
__rtw_enter_lps_deep(rtwdev);
}
void rtw_leave_lps(struct rtw_dev *rtwdev)
{
lockdep_assert_held(&rtwdev->mutex);
__rtw_leave_lps_deep(rtwdev);
__rtw_leave_lps(rtwdev);
}
void rtw_leave_lps_deep(struct rtw_dev *rtwdev)
{
lockdep_assert_held(&rtwdev->mutex);
__rtw_leave_lps_deep(rtwdev);
}

View File

@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_PS_H_
#define __RTW_PS_H_
#define RTW_LPS_THRESHOLD 50
#define POWER_MODE_ACK BIT(6)
#define POWER_MODE_PG BIT(4)
#define POWER_TX_WAKE BIT(1)
#define POWER_MODE_LCLK BIT(0)
#define LEAVE_LPS_TRY_CNT 5
#define LEAVE_LPS_TIMEOUT msecs_to_jiffies(100)
int rtw_enter_ips(struct rtw_dev *rtwdev);
int rtw_leave_ips(struct rtw_dev *rtwdev);
void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter);
void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id);
void rtw_leave_lps(struct rtw_dev *rtwdev);
void rtw_leave_lps_deep(struct rtw_dev *rtwdev);
enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev);
#endif

688
sys/contrib/dev/rtw88/reg.h Normal file
View File

@ -0,0 +1,688 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_REG_DEF_H__
#define __RTW_REG_DEF_H__
#define REG_SYS_FUNC_EN 0x0002
#define BIT_FEN_EN_25_1 BIT(13)
#define BIT_FEN_ELDR BIT(12)
#define BIT_FEN_CPUEN BIT(2)
#define BIT_FEN_BB_GLB_RST BIT(1)
#define BIT_FEN_BB_RSTB BIT(0)
#define BIT_R_DIS_PRST BIT(6)
#define BIT_WLOCK_1C_B6 BIT(5)
#define REG_SYS_PW_CTRL 0x0004
#define BIT_PFM_WOWL BIT(3)
#define REG_SYS_CLK_CTRL 0x0008
#define BIT_CPU_CLK_EN BIT(14)
#define REG_SYS_CLKR 0x0008
#define BIT_ANA8M BIT(1)
#define BIT_WAKEPAD_EN BIT(3)
#define BIT_LOADER_CLK_EN BIT(5)
#define REG_RSV_CTRL 0x001C
#define DISABLE_PI 0x3
#define ENABLE_PI 0x2
#define BITS_RFC_DIRECT (BIT(31) | BIT(30))
#define BIT_WLMCU_IOIF BIT(0)
#define REG_RF_CTRL 0x001F
#define BIT_RF_SDM_RSTB BIT(2)
#define BIT_RF_RSTB BIT(1)
#define BIT_RF_EN BIT(0)
#define REG_AFE_CTRL1 0x0024
#define BIT_MAC_CLK_SEL (BIT(20) | BIT(21))
#define REG_EFUSE_CTRL 0x0030
#define BIT_EF_FLAG BIT(31)
#define BIT_SHIFT_EF_ADDR 8
#define BIT_MASK_EF_ADDR 0x3ff
#define BIT_MASK_EF_DATA 0xff
#define BITS_EF_ADDR (BIT_MASK_EF_ADDR << BIT_SHIFT_EF_ADDR)
#define BITS_PLL 0xf0
#define REG_AFE_XTAL_CTRL 0x24
#define REG_AFE_PLL_CTRL 0x28
#define REG_AFE_CTRL3 0x2c
#define BIT_MASK_XTAL 0x00FFF000
#define BIT_XTAL_GMP_BIT4 BIT(28)
#define REG_LDO_EFUSE_CTRL 0x0034
#define BIT_MASK_EFUSE_BANK_SEL (BIT(8) | BIT(9))
#define BIT_LDO25_VOLTAGE_V25 0x03
#define BIT_MASK_LDO25_VOLTAGE GENMASK(6, 4)
#define BIT_SHIFT_LDO25_VOLTAGE 4
#define BIT_LDO25_EN BIT(7)
#define REG_GPIO_MUXCFG 0x0040
#define BIT_FSPI_EN BIT(19)
#define BIT_EN_SIC BIT(12)
#define BIT_PO_BT_PTA_PINS BIT(9)
#define BIT_BT_PTA_EN BIT(5)
#define BIT_WLRFE_4_5_EN BIT(2)
#define REG_LED_CFG 0x004C
#define BIT_LNAON_SEL_EN BIT(26)
#define BIT_PAPE_SEL_EN BIT(25)
#define BIT_DPDT_WL_SEL BIT(24)
#define BIT_DPDT_SEL_EN BIT(23)
#define REG_LEDCFG2 0x004E
#define REG_PAD_CTRL1 0x0064
#define BIT_BT_BTG_SEL BIT(31)
#define BIT_PAPE_WLBT_SEL BIT(29)
#define BIT_LNAON_WLBT_SEL BIT(28)
#define BIT_BTGP_JTAG_EN BIT(24)
#define BIT_BTGP_SPI_EN BIT(20)
#define BIT_LED1DIS BIT(15)
#define BIT_SW_DPDT_SEL_DATA BIT(0)
#define REG_WL_BT_PWR_CTRL 0x0068
#define BIT_BT_FUNC_EN BIT(18)
#define BIT_BT_DIG_CLK_EN BIT(8)
#define REG_SYS_SDIO_CTRL 0x0070
#define BIT_DBG_GNT_WL_BT BIT(27)
#define BIT_LTE_MUX_CTRL_PATH BIT(26)
#define REG_HCI_OPT_CTRL 0x0074
#define BIT_USB_SUS_DIS BIT(8)
#define REG_AFE_CTRL_4 0x0078
#define BIT_CK320M_AFE_EN BIT(4)
#define BIT_EN_SYN BIT(15)
#define REG_LDO_SWR_CTRL 0x007C
#define LDO_SEL 0xC3
#define SPS_SEL 0x83
#define BIT_XTA1 BIT(29)
#define BIT_XTA0 BIT(28)
#define REG_MCUFW_CTRL 0x0080
#define BIT_ANA_PORT_EN BIT(22)
#define BIT_MAC_PORT_EN BIT(21)
#define BIT_BOOT_FSPI_EN BIT(20)
#define BIT_ROM_DLEN BIT(19)
#define BIT_ROM_PGE GENMASK(18, 16) /* legacy only */
#define BIT_SHIFT_ROM_PGE 16
#define BIT_FW_INIT_RDY BIT(15)
#define BIT_FW_DW_RDY BIT(14)
#define BIT_RPWM_TOGGLE BIT(7)
#define BIT_RAM_DL_SEL BIT(7) /* legacy only */
#define BIT_DMEM_CHKSUM_OK BIT(6)
#define BIT_WINTINI_RDY BIT(6) /* legacy only */
#define BIT_DMEM_DW_OK BIT(5)
#define BIT_IMEM_CHKSUM_OK BIT(4)
#define BIT_IMEM_DW_OK BIT(3)
#define BIT_IMEM_BOOT_LOAD_CHECKSUM_OK BIT(2)
#define BIT_FWDL_CHK_RPT BIT(2) /* legacy only */
#define BIT_MCUFWDL_RDY BIT(1) /* legacy only */
#define BIT_MCUFWDL_EN BIT(0)
#define BIT_CHECK_SUM_OK (BIT(4) | BIT(6))
#define FW_READY (BIT_FW_INIT_RDY | BIT_FW_DW_RDY | \
BIT_IMEM_DW_OK | BIT_DMEM_DW_OK | \
BIT_CHECK_SUM_OK)
#define FW_READY_LEGACY (BIT_MCUFWDL_RDY | BIT_FWDL_CHK_RPT | \
BIT_WINTINI_RDY | BIT_RAM_DL_SEL)
#define FW_READY_MASK 0xffff
#define REG_MCU_TST_CFG 0x84
#define VAL_FW_TRIGGER 0x1
#define REG_PMC_DBG_CTRL1 0xa8
#define BITS_PMC_BT_IQK_STS GENMASK(22, 21)
#define REG_EFUSE_ACCESS 0x00CF
#define EFUSE_ACCESS_ON 0x69
#define EFUSE_ACCESS_OFF 0x00
#define REG_WLRF1 0x00EC
#define REG_WIFI_BT_INFO 0x00AA
#define BIT_BT_INT_EN BIT(15)
#define REG_SYS_CFG1 0x00F0
#define BIT_RTL_ID BIT(23)
#define BIT_LDO BIT(24)
#define BIT_RF_TYPE_ID BIT(27)
#define BIT_SHIFT_VENDOR_ID 16
#define BIT_MASK_VENDOR_ID 0xf
#define BIT_VENDOR_ID(x) (((x) & BIT_MASK_VENDOR_ID) << BIT_SHIFT_VENDOR_ID)
#define BITS_VENDOR_ID (BIT_MASK_VENDOR_ID << BIT_SHIFT_VENDOR_ID)
#define BIT_CLEAR_VENDOR_ID(x) ((x) & (~BITS_VENDOR_ID))
#define BIT_GET_VENDOR_ID(x) (((x) >> BIT_SHIFT_VENDOR_ID) & BIT_MASK_VENDOR_ID)
#define BIT_SHIFT_CHIP_VER 12
#define BIT_MASK_CHIP_VER 0xf
#define BIT_CHIP_VER(x) (((x) & BIT_MASK_CHIP_VER) << BIT_SHIFT_CHIP_VER)
#define BITS_CHIP_VER (BIT_MASK_CHIP_VER << BIT_SHIFT_CHIP_VER)
#define BIT_CLEAR_CHIP_VER(x) ((x) & (~BITS_CHIP_VER))
#define BIT_GET_CHIP_VER(x) (((x) >> BIT_SHIFT_CHIP_VER) & BIT_MASK_CHIP_VER)
#define REG_SYS_STATUS1 0x00F4
#define REG_SYS_STATUS2 0x00F8
#define REG_SYS_CFG2 0x00FC
#define REG_WLRF1 0x00EC
#define BIT_WLRF1_BBRF_EN (BIT(24) | BIT(25) | BIT(26))
#define REG_CR 0x0100
#define BIT_32K_CAL_TMR_EN BIT(10)
#define BIT_MAC_SEC_EN BIT(9)
#define BIT_ENSWBCN BIT(8)
#define BIT_MACRXEN BIT(7)
#define BIT_MACTXEN BIT(6)
#define BIT_SCHEDULE_EN BIT(5)
#define BIT_PROTOCOL_EN BIT(4)
#define BIT_RXDMA_EN BIT(3)
#define BIT_TXDMA_EN BIT(2)
#define BIT_HCI_RXDMA_EN BIT(1)
#define BIT_HCI_TXDMA_EN BIT(0)
#define MAC_TRX_ENABLE (BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN | \
BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN | \
BIT_MACTXEN | BIT_MACRXEN)
#define BIT_SHIFT_TXDMA_VOQ_MAP 4
#define BIT_MASK_TXDMA_VOQ_MAP 0x3
#define BIT_TXDMA_VOQ_MAP(x) \
(((x) & BIT_MASK_TXDMA_VOQ_MAP) << BIT_SHIFT_TXDMA_VOQ_MAP)
#define BIT_SHIFT_TXDMA_VIQ_MAP 6
#define BIT_MASK_TXDMA_VIQ_MAP 0x3
#define BIT_TXDMA_VIQ_MAP(x) \
(((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP)
#define REG_TXDMA_PQ_MAP 0x010C
#define BIT_SHIFT_TXDMA_BEQ_MAP 8
#define BIT_MASK_TXDMA_BEQ_MAP 0x3
#define BIT_TXDMA_BEQ_MAP(x) \
(((x) & BIT_MASK_TXDMA_BEQ_MAP) << BIT_SHIFT_TXDMA_BEQ_MAP)
#define BIT_SHIFT_TXDMA_BKQ_MAP 10
#define BIT_MASK_TXDMA_BKQ_MAP 0x3
#define BIT_TXDMA_BKQ_MAP(x) \
(((x) & BIT_MASK_TXDMA_BKQ_MAP) << BIT_SHIFT_TXDMA_BKQ_MAP)
#define BIT_SHIFT_TXDMA_MGQ_MAP 12
#define BIT_MASK_TXDMA_MGQ_MAP 0x3
#define BIT_TXDMA_MGQ_MAP(x) \
(((x) & BIT_MASK_TXDMA_MGQ_MAP) << BIT_SHIFT_TXDMA_MGQ_MAP)
#define BIT_SHIFT_TXDMA_HIQ_MAP 14
#define BIT_MASK_TXDMA_HIQ_MAP 0x3
#define BIT_TXDMA_HIQ_MAP(x) \
(((x) & BIT_MASK_TXDMA_HIQ_MAP) << BIT_SHIFT_TXDMA_HIQ_MAP)
#define BIT_SHIFT_TXSC_40M 4
#define BIT_MASK_TXSC_40M 0xf
#define BIT_TXSC_40M(x) \
(((x) & BIT_MASK_TXSC_40M) << BIT_SHIFT_TXSC_40M)
#define BIT_SHIFT_TXSC_20M 0
#define BIT_MASK_TXSC_20M 0xf
#define BIT_TXSC_20M(x) \
(((x) & BIT_MASK_TXSC_20M) << BIT_SHIFT_TXSC_20M)
#define BIT_SHIFT_MAC_CLK_SEL 20
#define MAC_CLK_HW_DEF_80M 0
#define MAC_CLK_HW_DEF_40M 1
#define MAC_CLK_HW_DEF_20M 2
#define MAC_CLK_SPEED 80
#define REG_CR 0x0100
#define REG_TRXFF_BNDY 0x0114
#define REG_RXFF_BNDY 0x011C
#define REG_FE1IMR 0x0120
#define BIT_FS_RXDONE BIT(16)
#define REG_PKTBUF_DBG_CTRL 0x0140
#define REG_C2HEVT 0x01A0
#define REG_MCUTST_1 0x01C0
#define REG_MCUTST_II 0x01C4
#define REG_WOWLAN_WAKE_REASON 0x01C7
#define REG_HMETFR 0x01CC
#define REG_HMEBOX0 0x01D0
#define REG_HMEBOX1 0x01D4
#define REG_HMEBOX2 0x01D8
#define REG_HMEBOX3 0x01DC
#define REG_HMEBOX0_EX 0x01F0
#define REG_HMEBOX1_EX 0x01F4
#define REG_HMEBOX2_EX 0x01F8
#define REG_HMEBOX3_EX 0x01FC
#define REG_RQPN 0x0200
#define BIT_MASK_HPQ 0xff
#define BIT_SHIFT_HPQ 0
#define BIT_RQPN_HPQ(x) (((x) & BIT_MASK_HPQ) << BIT_SHIFT_HPQ)
#define BIT_MASK_LPQ 0xff
#define BIT_SHIFT_LPQ 8
#define BIT_RQPN_LPQ(x) (((x) & BIT_MASK_LPQ) << BIT_SHIFT_LPQ)
#define BIT_MASK_PUBQ 0xff
#define BIT_SHIFT_PUBQ 16
#define BIT_RQPN_PUBQ(x) (((x) & BIT_MASK_PUBQ) << BIT_SHIFT_PUBQ)
#define BIT_RQPN_HLP(h, l, p) (BIT_LD_RQPN | BIT_RQPN_HPQ(h) | \
BIT_RQPN_LPQ(l) | BIT_RQPN_PUBQ(p))
#define REG_FIFOPAGE_CTRL_2 0x0204
#define BIT_BCN_VALID_V1 BIT(15)
#define BIT_MASK_BCN_HEAD_1_V1 0xfff
#define REG_AUTO_LLT_V1 0x0208
#define BIT_AUTO_INIT_LLT_V1 BIT(0)
#define REG_DWBCN0_CTRL 0x0208
#define BIT_BCN_VALID BIT(16)
#define REG_TXDMA_OFFSET_CHK 0x020C
#define BIT_DROP_DATA_EN BIT(9)
#define REG_TXDMA_STATUS 0x0210
#define BTI_PAGE_OVF BIT(2)
#define REG_RQPN_NPQ 0x0214
#define BIT_MASK_NPQ 0xff
#define BIT_SHIFT_NPQ 0
#define BIT_MASK_EPQ 0xff
#define BIT_SHIFT_EPQ 16
#define BIT_RQPN_NPQ(x) (((x) & BIT_MASK_NPQ) << BIT_SHIFT_NPQ)
#define BIT_RQPN_EPQ(x) (((x) & BIT_MASK_EPQ) << BIT_SHIFT_EPQ)
#define BIT_RQPN_NE(n, e) (BIT_RQPN_NPQ(n) | BIT_RQPN_EPQ(e))
#define REG_AUTO_LLT 0x0224
#define BIT_AUTO_INIT_LLT BIT(16)
#define REG_RQPN_CTRL_1 0x0228
#define REG_RQPN_CTRL_2 0x022C
#define BIT_LD_RQPN BIT(31)
#define REG_FIFOPAGE_INFO_1 0x0230
#define REG_FIFOPAGE_INFO_2 0x0234
#define REG_FIFOPAGE_INFO_3 0x0238
#define REG_FIFOPAGE_INFO_4 0x023C
#define REG_FIFOPAGE_INFO_5 0x0240
#define REG_H2C_HEAD 0x0244
#define REG_H2C_TAIL 0x0248
#define REG_H2C_READ_ADDR 0x024C
#define REG_H2C_INFO 0x0254
#define REG_RXPKT_NUM 0x0284
#define BIT_RXDMA_REQ BIT(19)
#define BIT_RW_RELEASE BIT(18)
#define BIT_RXDMA_IDLE BIT(17)
#define REG_RXPKTNUM 0x02B0
#define REG_INT_MIG 0x0304
#define REG_HCI_MIX_CFG 0x03FC
#define BIT_PCIE_EMAC_PDN_AUX_TO_FAST_CLK BIT(26)
#define REG_BCNQ_INFO 0x0418
#define BIT_MGQ_CPU_EMPTY BIT(24)
#define REG_FWHW_TXQ_CTRL 0x0420
#define BIT_EN_BCNQ_DL BIT(22)
#define BIT_EN_WR_FREE_TAIL BIT(20)
#define REG_HWSEQ_CTRL 0x0423
#define REG_BCNQ_BDNY_V1 0x0424
#define REG_BCNQ_BDNY 0x0424
#define REG_MGQ_BDNY 0x0425
#define REG_LIFETIME_EN 0x0426
#define BIT_BA_PARSER_EN BIT(5)
#define REG_SPEC_SIFS 0x0428
#define REG_RETRY_LIMIT 0x042a
#define REG_DARFRC 0x0430
#define REG_DARFRCH 0x0434
#define REG_RARFRCH 0x043C
#define REG_RRSR 0x0440
#define BITS_RRSR_RSC GENMASK(22, 21)
#define REG_ARFR0 0x0444
#define REG_ARFRH0 0x0448
#define REG_ARFR1_V1 0x044C
#define REG_ARFRH1_V1 0x0450
#define REG_CCK_CHECK 0x0454
#define BIT_CHECK_CCK_EN BIT(7)
#define REG_AMPDU_MAX_TIME_V1 0x0455
#define REG_BCNQ1_BDNY_V1 0x0456
#define REG_AMPDU_MAX_TIME 0x0456
#define REG_WMAC_LBK_BF_HD 0x045D
#define REG_TX_HANG_CTRL 0x045E
#define BIT_EN_GNT_BT_AWAKE BIT(3)
#define BIT_EN_EOF_V1 BIT(2)
#define REG_DATA_SC 0x0483
#define REG_ARFR4 0x049C
#define BIT_WL_RFK BIT(0)
#define REG_ARFRH4 0x04A0
#define REG_ARFR5 0x04A4
#define REG_ARFRH5 0x04A8
#define REG_SW_AMPDU_BURST_MODE_CTRL 0x04BC
#define BIT_PRE_TX_CMD BIT(6)
#define REG_QUEUE_CTRL 0x04C6
#define BIT_PTA_WL_TX_EN BIT(4)
#define BIT_PTA_EDCCA_EN BIT(5)
#define REG_SINGLE_AMPDU_CTRL 0x04C7
#define BIT_EN_SINGLE_APMDU BIT(7)
#define REG_PROT_MODE_CTRL 0x04C8
#define REG_MAX_AGGR_NUM 0x04CA
#define REG_BAR_MODE_CTRL 0x04CC
#define REG_PRECNT_CTRL 0x04E5
#define BIT_BTCCA_CTRL (BIT(0) | BIT(1))
#define BIT_EN_PRECNT BIT(11)
#define REG_DUMMY_PAGE4_V1 0x04FC
#define REG_EDCA_VO_PARAM 0x0500
#define REG_EDCA_VI_PARAM 0x0504
#define REG_EDCA_BE_PARAM 0x0508
#define REG_EDCA_BK_PARAM 0x050C
#define BIT_MASK_TXOP_LMT GENMASK(26, 16)
#define BIT_MASK_CWMAX GENMASK(15, 12)
#define BIT_MASK_CWMIN GENMASK(11, 8)
#define BIT_MASK_AIFS GENMASK(7, 0)
#define REG_PIFS 0x0512
#define REG_SIFS 0x0514
#define BIT_SHIFT_SIFS_OFDM_CTX 8
#define BIT_SHIFT_SIFS_CCK_TRX 16
#define BIT_SHIFT_SIFS_OFDM_TRX 24
#define REG_AGGR_BREAK_TIME 0x051A
#define REG_SLOT 0x051B
#define REG_TX_PTCL_CTRL 0x0520
#define BIT_DIS_EDCCA BIT(15)
#define BIT_SIFS_BK_EN BIT(12)
#define REG_TXPAUSE 0x0522
#define BIT_AC_QUEUE GENMASK(7, 0)
#define REG_RD_CTRL 0x0524
#define BIT_EDCCA_MSK_CNTDOWN_EN BIT(11)
#define BIT_DIS_TXOP_CFE BIT(10)
#define BIT_DIS_LSIG_CFE BIT(9)
#define BIT_DIS_STBC_CFE BIT(8)
#define REG_TBTT_PROHIBIT 0x0540
#define BIT_SHIFT_TBTT_HOLD_TIME_AP 8
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
#define BIT_DIS_TSF_UDT BIT(4)
#define BIT_EN_BCN_FUNCTION BIT(3)
#define BIT_EN_TXBCN_RPT BIT(2)
#define REG_BCN_CTRL_CLINT0 0x0551
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_MISC_CTRL 0x0577
#define BIT_EN_FREE_CNT BIT(3)
#define BIT_DIS_SECOND_CCA (BIT(0) | BIT(1))
#define REG_HIQ_NO_LMT_EN 0x5A7
#define BIT_HIQ_NO_LMT_EN_ROOT BIT(0)
#define REG_TIMER0_SRC_SEL 0x05B4
#define BIT_TSFT_SEL_TIMER0 (BIT(4) | BIT(5) | BIT(6))
#define REG_TCR 0x0604
#define BIT_PWRMGT_HWDATA_EN BIT(7)
#define REG_RCR 0x0608
#define BIT_APP_FCS BIT(31)
#define BIT_APP_MIC BIT(30)
#define BIT_APP_ICV BIT(29)
#define BIT_APP_PHYSTS BIT(28)
#define BIT_APP_BASSN BIT(27)
#define BIT_VHT_DACK BIT(26)
#define BIT_TCPOFLD_EN BIT(25)
#define BIT_ENMBID BIT(24)
#define BIT_LSIGEN BIT(23)
#define BIT_MFBEN BIT(22)
#define BIT_DISCHKPPDLLEN BIT(21)
#define BIT_PKTCTL_DLEN BIT(20)
#define BIT_DISGCLK BIT(19)
#define BIT_TIM_PARSER_EN BIT(18)
#define BIT_BC_MD_EN BIT(17)
#define BIT_UC_MD_EN BIT(16)
#define BIT_RXSK_PERPKT BIT(15)
#define BIT_HTC_LOC_CTRL BIT(14)
#define BIT_RPFM_CAM_ENABLE BIT(12)
#define BIT_TA_BCN BIT(11)
#define BIT_RCR_ADF BIT(11)
#define BIT_DISDECMYPKT BIT(10)
#define BIT_AICV BIT(9)
#define BIT_ACRC32 BIT(8)
#define BIT_CBSSID_BCN BIT(7)
#define BIT_CBSSID_DATA BIT(6)
#define BIT_APWRMGT BIT(5)
#define BIT_ADD3 BIT(4)
#define BIT_AB BIT(3)
#define BIT_AM BIT(2)
#define BIT_APM BIT(1)
#define BIT_AAP BIT(0)
#define REG_RX_PKT_LIMIT 0x060C
#define REG_RX_DRVINFO_SZ 0x060F
#define BIT_APP_PHYSTS BIT(28)
#define REG_MAR 0x0620
#define REG_USTIME_EDCA 0x0638
#define REG_ACKTO_CCK 0x0639
#define REG_MAC_SPEC_SIFS 0x063A
#define REG_RESP_SIFS_CCK 0x063C
#define REG_RESP_SIFS_OFDM 0x063E
#define REG_ACKTO 0x0640
#define REG_EIFS 0x0642
#define REG_NAV_CTRL 0x0650
#define REG_WMAC_TRXPTCL_CTL 0x0668
#define BIT_RFMOD (BIT(7) | BIT(8))
#define BIT_RFMOD_80M BIT(8)
#define BIT_RFMOD_40M BIT(7)
#define REG_WMAC_TRXPTCL_CTL_H 0x066C
#define REG_WKFMCAM_CMD 0x0698
#define BIT_WKFCAM_POLLING_V1 BIT(31)
#define BIT_WKFCAM_CLR_V1 BIT(30)
#define BIT_WKFCAM_WE BIT(16)
#define BIT_SHIFT_WKFCAM_ADDR_V2 8
#define BIT_MASK_WKFCAM_ADDR_V2 0xff
#define BIT_WKFCAM_ADDR_V2(x) \
(((x) & BIT_MASK_WKFCAM_ADDR_V2) << BIT_SHIFT_WKFCAM_ADDR_V2)
#define REG_WKFMCAM_RWD 0x069C
#define BIT_WKFMCAM_VALID BIT(31)
#define BIT_WKFMCAM_BC BIT(26)
#define BIT_WKFMCAM_MC BIT(25)
#define BIT_WKFMCAM_UC BIT(24)
#define REG_RXFLTMAP0 0x06A0
#define REG_RXFLTMAP1 0x06A2
#define REG_RXFLTMAP2 0x06A4
#define REG_RXFLTMAP4 0x068A
#define REG_BT_COEX_TABLE0 0x06C0
#define REG_BT_COEX_TABLE1 0x06C4
#define REG_BT_COEX_BRK_TABLE 0x06C8
#define REG_BT_COEX_TABLE_H 0x06CC
#define REG_BT_COEX_TABLE_H1 0x06CD
#define REG_BT_COEX_TABLE_H2 0x06CE
#define REG_BT_COEX_TABLE_H3 0x06CF
#define REG_BBPSF_CTRL 0x06DC
#define REG_BT_COEX_V2 0x0762
#define BIT_GNT_BT_POLARITY BIT(12)
#define BIT_LTE_COEX_EN BIT(7)
#define REG_BT_COEX_ENH_INTR_CTRL 0x76E
#define BIT_R_GRANTALL_WLMASK BIT(3)
#define BIT_STATIS_BT_EN BIT(2)
#define REG_BT_ACT_STATISTICS 0x0770
#define REG_BT_ACT_STATISTICS_1 0x0774
#define REG_BT_STAT_CTRL 0x0778
#define REG_BT_TDMA_TIME 0x0790
#define BIT_MASK_SAMPLE_RATE GENMASK(5, 0)
#define REG_LTR_IDLE_LATENCY 0x0798
#define REG_LTR_ACTIVE_LATENCY 0x079C
#define REG_LTR_CTRL_BASIC 0x07A4
#define REG_WMAC_OPTION_FUNCTION 0x07D0
#define REG_WMAC_OPTION_FUNCTION_1 0x07D4
#define REG_FPGA0_RFMOD 0x0800
#define BIT_CCKEN BIT(24)
#define BIT_OFDMEN BIT(25)
#define REG_RX_GAIN_EN 0x081c
#define REG_RFE_CTRL_E 0x0974
#define REG_2ND_CCA_CTRL 0x0976
#define REG_CCK0_FAREPORT 0xa2c
#define BIT_CCK0_2RX BIT(18)
#define BIT_CCK0_MRC BIT(22)
#define REG_DIS_DPD 0x0a70
#define DIS_DPD_MASK GENMASK(9, 0)
#define DIS_DPD_RATE6M BIT(0)
#define DIS_DPD_RATE9M BIT(1)
#define DIS_DPD_RATEMCS0 BIT(2)
#define DIS_DPD_RATEMCS1 BIT(3)
#define DIS_DPD_RATEMCS8 BIT(4)
#define DIS_DPD_RATEMCS9 BIT(5)
#define DIS_DPD_RATEVHT1SS_MCS0 BIT(6)
#define DIS_DPD_RATEVHT1SS_MCS1 BIT(7)
#define DIS_DPD_RATEVHT2SS_MCS0 BIT(8)
#define DIS_DPD_RATEVHT2SS_MCS1 BIT(9)
#define DIS_DPD_RATEALL GENMASK(9, 0)
#define REG_RFE_CTRL8 0x0cb4
#define BIT_MASK_RFE_SEL89 GENMASK(7, 0)
#define REG_RFE_INV8 0x0cbd
#define BIT_MASK_RFE_INV89 GENMASK(1, 0)
#define REG_RFE_INV16 0x0cbe
#define BIT_RFE_BUF_EN BIT(3)
#define REG_ANAPAR_XTAL_0 0x1040
#define BIT_XCAP_0 GENMASK(23, 10)
#define REG_CPU_DMEM_CON 0x1080
#define BIT_WL_PLATFORM_RST BIT(16)
#define BIT_WL_SECURITY_CLK BIT(15)
#define BIT_DDMA_EN BIT(8)
#define REG_H2C_PKT_READADDR 0x10D0
#define REG_H2C_PKT_WRITEADDR 0x10D4
#define REG_FW_DBG7 0x10FC
#define FW_KEY_MASK 0xffffff00
#define REG_CR_EXT 0x1100
#define REG_DDMA_CH0SA 0x1200
#define REG_DDMA_CH0DA 0x1204
#define REG_DDMA_CH0CTRL 0x1208
#define BIT_DDMACH0_OWN BIT(31)
#define BIT_DDMACH0_CHKSUM_EN BIT(29)
#define BIT_DDMACH0_CHKSUM_STS BIT(27)
#define BIT_DDMACH0_DDMA_MODE BIT(26)
#define BIT_DDMACH0_RESET_CHKSUM_STS BIT(25)
#define BIT_DDMACH0_CHKSUM_CONT BIT(24)
#define BIT_MASK_DDMACH0_DLEN 0x3ffff
#define REG_H2CQ_CSR 0x1330
#define BIT_H2CQ_FULL BIT(31)
#define REG_FAST_EDCA_VOVI_SETTING 0x1448
#define REG_FAST_EDCA_BEBK_SETTING 0x144C
#define REG_RXPSF_CTRL 0x1610
#define BIT_RXGCK_FIFOTHR_EN BIT(28)
#define BIT_SHIFT_RXGCK_VHT_FIFOTHR 26
#define BIT_MASK_RXGCK_VHT_FIFOTHR 0x3
#define BIT_RXGCK_VHT_FIFOTHR(x) \
(((x) & BIT_MASK_RXGCK_VHT_FIFOTHR) << BIT_SHIFT_RXGCK_VHT_FIFOTHR)
#define BITS_RXGCK_VHT_FIFOTHR \
(BIT_MASK_RXGCK_VHT_FIFOTHR << BIT_SHIFT_RXGCK_VHT_FIFOTHR)
#define BIT_SHIFT_RXGCK_HT_FIFOTHR 24
#define BIT_MASK_RXGCK_HT_FIFOTHR 0x3
#define BIT_RXGCK_HT_FIFOTHR(x) \
(((x) & BIT_MASK_RXGCK_HT_FIFOTHR) << BIT_SHIFT_RXGCK_HT_FIFOTHR)
#define BITS_RXGCK_HT_FIFOTHR \
(BIT_MASK_RXGCK_HT_FIFOTHR << BIT_SHIFT_RXGCK_HT_FIFOTHR)
#define BIT_SHIFT_RXGCK_OFDM_FIFOTHR 22
#define BIT_MASK_RXGCK_OFDM_FIFOTHR 0x3
#define BIT_RXGCK_OFDM_FIFOTHR(x) \
(((x) & BIT_MASK_RXGCK_OFDM_FIFOTHR) << BIT_SHIFT_RXGCK_OFDM_FIFOTHR)
#define BITS_RXGCK_OFDM_FIFOTHR \
(BIT_MASK_RXGCK_OFDM_FIFOTHR << BIT_SHIFT_RXGCK_OFDM_FIFOTHR)
#define BIT_SHIFT_RXGCK_CCK_FIFOTHR 20
#define BIT_MASK_RXGCK_CCK_FIFOTHR 0x3
#define BIT_RXGCK_CCK_FIFOTHR(x) \
(((x) & BIT_MASK_RXGCK_CCK_FIFOTHR) << BIT_SHIFT_RXGCK_CCK_FIFOTHR)
#define BITS_RXGCK_CCK_FIFOTHR \
(BIT_MASK_RXGCK_CCK_FIFOTHR << BIT_SHIFT_RXGCK_CCK_FIFOTHR)
#define BIT_RXGCK_OFDMCCA_EN BIT(16)
#define BIT_SHIFT_RXPSF_PKTLENTHR 13
#define BIT_MASK_RXPSF_PKTLENTHR 0x7
#define BIT_RXPSF_PKTLENTHR(x) \
(((x) & BIT_MASK_RXPSF_PKTLENTHR) << BIT_SHIFT_RXPSF_PKTLENTHR)
#define BITS_RXPSF_PKTLENTHR \
(BIT_MASK_RXPSF_PKTLENTHR << BIT_SHIFT_RXPSF_PKTLENTHR)
#define BIT_CLEAR_RXPSF_PKTLENTHR(x) ((x) & (~BITS_RXPSF_PKTLENTHR))
#define BIT_SET_RXPSF_PKTLENTHR(x, v) \
(BIT_CLEAR_RXPSF_PKTLENTHR(x) | BIT_RXPSF_PKTLENTHR(v))
#define BIT_RXPSF_CTRLEN BIT(12)
#define BIT_RXPSF_VHTCHKEN BIT(11)
#define BIT_RXPSF_HTCHKEN BIT(10)
#define BIT_RXPSF_OFDMCHKEN BIT(9)
#define BIT_RXPSF_CCKCHKEN BIT(8)
#define BIT_RXPSF_OFDMRST BIT(7)
#define BIT_RXPSF_CCKRST BIT(6)
#define BIT_RXPSF_MHCHKEN BIT(5)
#define BIT_RXPSF_CONT_ERRCHKEN BIT(4)
#define BIT_RXPSF_ALL_ERRCHKEN BIT(3)
#define BIT_SHIFT_RXPSF_ERRTHR 0
#define BIT_MASK_RXPSF_ERRTHR 0x7
#define BIT_RXPSF_ERRTHR(x) \
(((x) & BIT_MASK_RXPSF_ERRTHR) << BIT_SHIFT_RXPSF_ERRTHR)
#define BITS_RXPSF_ERRTHR (BIT_MASK_RXPSF_ERRTHR << BIT_SHIFT_RXPSF_ERRTHR)
#define BIT_CLEAR_RXPSF_ERRTHR(x) ((x) & (~BITS_RXPSF_ERRTHR))
#define BIT_GET_RXPSF_ERRTHR(x) \
(((x) >> BIT_SHIFT_RXPSF_ERRTHR) & BIT_MASK_RXPSF_ERRTHR)
#define BIT_SET_RXPSF_ERRTHR(x, v) \
(BIT_CLEAR_RXPSF_ERRTHR(x) | BIT_RXPSF_ERRTHR(v))
#define REG_RXPSF_TYPE_CTRL 0x1614
#define REG_GENERAL_OPTION 0x1664
#define BIT_DUMMY_FCS_READY_MASK_EN BIT(9)
#define REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1 0x1700
#define REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1 0x1704
#define REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1 0x1708
#define LTECOEX_READY BIT(29)
#define LTECOEX_ACCESS_CTRL REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1
#define LTECOEX_WRITE_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1
#define LTECOEX_READ_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1
#define REG_IGN_GNT_BT1 0x1860
#define REG_RFESEL_CTRL 0x1990
#define REG_NOMASK_TXBT 0x1ca7
#define REG_ANAPAR 0x1c30
#define BIT_ANAPAR_BTPS BIT(22)
#define REG_RSTB_SEL 0x1c38
#define BIT_DAC_OFF_ENABLE BIT(4)
#define BIT_PI_IGNORE_GNT_BT BIT(3)
#define BIT_NOMASK_TXBT_ENABLE BIT(3)
#define REG_HRCV_MSG 0x1cf
#define REG_EDCCA_REPORT 0x2d38
#define BIT_EDCCA_FLAG BIT(24)
#define REG_IGN_GNTBT4 0x4160
#define RF_MODE 0x00
#define RF_MODOPT 0x01
#define RF_WLINT 0x01
#define RF_WLSEL 0x02
#define RF_DTXLOK 0x08
#define RF_CFGCH 0x18
#define BIT_BAND GENMASK(18, 16)
#define RF_RCK 0x1d
#define RF_LUTWA 0x33
#define RF_LUTWD1 0x3e
#define RF_LUTWD0 0x3f
#define BIT_GAIN_EXT BIT(12)
#define BIT_DATA_L GENMASK(11, 0)
#define RF_T_METER 0x42
#define RF_BSPAD 0x54
#define RF_GAINTX 0x56
#define RF_TXATANK 0x64
#define RF_TRXIQ 0x66
#define RF_RXIQGEN 0x8d
#define RF_SYN_PFD 0xb0
#define RF_XTALX2 0xb8
#define RF_SYN_CTRL 0xbb
#define RF_MALSEL 0xbe
#define RF_SYN_AAC 0xc9
#define RF_AAC_CTRL 0xca
#define RF_FAST_LCK 0xcc
#define RF_RCKD 0xde
#define RF_TXADBG 0xde
#define RF_LUTDBG 0xdf
#define BIT_TXA_TANK BIT(4)
#define RF_LUTWE2 0xee
#define RF_LUTWE 0xef
#define LTE_COEX_CTRL 0x38
#define LTE_WL_TRX_CTRL 0xa0
#define LTE_BT_TRX_CTRL 0xa4
#endif

View File

@ -0,0 +1,529 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "regd.h"
#include "debug.h"
#include "phy.h"
#define COUNTRY_REGD_ENT(_alpha2, _regd_2g, _regd_5g) \
{.alpha2 = (_alpha2), \
.txpwr_regd_2g = (_regd_2g), \
.txpwr_regd_5g = (_regd_5g), \
}
#define rtw_dbg_regd_dump(_dev, _msg, _args...) \
do { \
struct rtw_dev *__d = (_dev); \
const struct rtw_regd *__r = &__d->regd; \
rtw_dbg(__d, RTW_DBG_REGD, _msg \
"apply alpha2 %c%c, regd {%d, %d}, dfs_region %d\n",\
##_args, \
__r->regulatory->alpha2[0], \
__r->regulatory->alpha2[1], \
__r->regulatory->txpwr_regd_2g, \
__r->regulatory->txpwr_regd_5g, \
__r->dfs_region); \
} while (0)
/* If country code is not correctly defined in efuse,
* use worldwide country code and txpwr regd.
*/
static const struct rtw_regulatory rtw_reg_ww =
COUNTRY_REGD_ENT("00", RTW_REGD_WW, RTW_REGD_WW);
static const struct rtw_regulatory rtw_reg_map[] = {
COUNTRY_REGD_ENT("AD", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("AE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("AF", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("AG", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("AI", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("AL", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("AM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("AN", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("AO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("AQ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("AR", RTW_REGD_MEXICO, RTW_REGD_MEXICO),
COUNTRY_REGD_ENT("AS", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("AT", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("AU", RTW_REGD_ACMA, RTW_REGD_ACMA),
COUNTRY_REGD_ENT("AW", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("AZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BB", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("BD", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BF", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BH", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BI", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BJ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BM", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("BN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BO", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("BR", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("BS", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("BT", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BV", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BW", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BY", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BZ", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("CA", RTW_REGD_IC, RTW_REGD_IC),
COUNTRY_REGD_ENT("CC", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CD", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CF", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CH", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CI", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CL", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("CM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CO", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("CR", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("CV", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CX", RTW_REGD_ACMA, RTW_REGD_ACMA),
COUNTRY_REGD_ENT("CY", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("DE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("DJ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("DK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("DM", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("DO", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("DZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("EC", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("EE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("EG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("EH", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("ER", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("ES", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("ET", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("FI", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("FJ", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("FK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("FM", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("FO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("FR", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GB", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GD", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("GE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GF", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GH", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GI", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GL", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GP", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GQ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GR", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GS", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GT", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("GU", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("GW", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GY", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("HK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("HM", RTW_REGD_ACMA, RTW_REGD_ACMA),
COUNTRY_REGD_ENT("HN", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("HR", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("HT", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("HU", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("ID", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("IE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("IL", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("IM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("IN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("IO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("IQ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("IR", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("IS", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("IT", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("JE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("JM", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("JO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("JP", RTW_REGD_MKK, RTW_REGD_MKK),
COUNTRY_REGD_ENT("KE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("KG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("KH", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("KI", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("KM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("KN", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("KR", RTW_REGD_KCC, RTW_REGD_KCC),
COUNTRY_REGD_ENT("KW", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("KY", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("KZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LB", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LC", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("LI", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LR", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LS", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LT", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LU", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LV", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("LY", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MC", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MD", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("ME", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MF", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("MG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MH", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("MK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("ML", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MP", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("MQ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MR", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MS", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MT", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MU", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MV", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MW", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MX", RTW_REGD_MEXICO, RTW_REGD_MEXICO),
COUNTRY_REGD_ENT("MY", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("MZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("NA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("NC", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("NE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("NF", RTW_REGD_ACMA, RTW_REGD_ACMA),
COUNTRY_REGD_ENT("NG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("NI", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("NL", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("NO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("NP", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("NR", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("NU", RTW_REGD_ACMA, RTW_REGD_ACMA),
COUNTRY_REGD_ENT("NZ", RTW_REGD_ACMA, RTW_REGD_ACMA),
COUNTRY_REGD_ENT("OM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PA", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("PE", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("PF", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PH", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PL", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PR", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("PS", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PT", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PW", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("PY", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("QA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("RE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("RO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("RS", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("RU", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("RW", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SB", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SC", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("SE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SH", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SI", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SJ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SL", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SR", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("ST", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("SV", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("SX", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("SZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TC", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TD", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TF", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TH", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TJ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TK", RTW_REGD_ACMA, RTW_REGD_ACMA),
COUNTRY_REGD_ENT("TM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TR", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("TT", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("TV", RTW_REGD_ETSI, RTW_REGD_WW),
COUNTRY_REGD_ENT("TW", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("TZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("UA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("UG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("US", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("UY", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("UZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("VA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("VC", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("VE", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("VG", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("VI", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("VN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("VU", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("WF", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("WS", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("XK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("YE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("YT", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("ZA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("ZM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("ZW", RTW_REGD_ETSI, RTW_REGD_ETSI),
};
static void rtw_regd_apply_hw_cap_flags(struct wiphy *wiphy)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ieee80211_supported_band *sband;
struct ieee80211_channel *ch;
struct rtw_dev *rtwdev = hw->priv;
struct rtw_efuse *efuse = &rtwdev->efuse;
int i;
if (efuse->hw_cap.bw & BIT(RTW_CHANNEL_WIDTH_80))
return;
sband = wiphy->bands[NL80211_BAND_2GHZ];
if (!sband)
goto out_5g;
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
ch->flags |= IEEE80211_CHAN_NO_80MHZ;
}
out_5g:
sband = wiphy->bands[NL80211_BAND_5GHZ];
if (!sband)
return;
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
ch->flags |= IEEE80211_CHAN_NO_80MHZ;
}
}
static bool rtw_reg_is_ww(const struct rtw_regulatory *reg)
{
return reg == &rtw_reg_ww;
}
static bool rtw_reg_match(const struct rtw_regulatory *reg, const char *alpha2)
{
return memcmp(reg->alpha2, alpha2, 2) == 0;
}
static const struct rtw_regulatory *rtw_reg_find_by_name(const char *alpha2)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(rtw_reg_map); i++) {
if (rtw_reg_match(&rtw_reg_map[i], alpha2))
return &rtw_reg_map[i];
}
return &rtw_reg_ww;
}
static
void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request);
/* call this before ieee80211_register_hw() */
int rtw_regd_init(struct rtw_dev *rtwdev)
{
struct wiphy *wiphy = rtwdev->hw->wiphy;
const struct rtw_regulatory *chip_reg;
if (!wiphy)
return -EINVAL;
wiphy->reg_notifier = rtw_regd_notifier;
chip_reg = rtw_reg_find_by_name(rtwdev->efuse.country_code);
if (!rtw_reg_is_ww(chip_reg)) {
rtwdev->regd.state = RTW_REGD_STATE_PROGRAMMED;
/* Set REGULATORY_STRICT_REG before ieee80211_register_hw(),
* stack will wait for regulatory_hint() and consider it
* as the superset for our regulatory rule.
*/
wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
} else {
rtwdev->regd.state = RTW_REGD_STATE_WORLDWIDE;
}
rtwdev->regd.regulatory = &rtw_reg_ww;
rtwdev->regd.dfs_region = NL80211_DFS_UNSET;
rtw_dbg_regd_dump(rtwdev, "regd init state %d: ", rtwdev->regd.state);
rtw_regd_apply_hw_cap_flags(wiphy);
return 0;
}
/* call this after ieee80211_register_hw() */
int rtw_regd_hint(struct rtw_dev *rtwdev)
{
struct wiphy *wiphy = rtwdev->hw->wiphy;
int ret;
if (!wiphy)
return -EINVAL;
if (rtwdev->regd.state == RTW_REGD_STATE_PROGRAMMED) {
rtw_dbg(rtwdev, RTW_DBG_REGD,
"country domain %c%c is PGed on efuse",
rtwdev->efuse.country_code[0],
rtwdev->efuse.country_code[1]);
ret = regulatory_hint(wiphy, rtwdev->efuse.country_code);
if (ret) {
rtw_warn(rtwdev,
"failed to hint regulatory: %d\n", ret);
return ret;
}
}
return 0;
}
static bool rtw_regd_mgmt_worldwide(struct rtw_dev *rtwdev,
struct rtw_regd *next_regd,
struct regulatory_request *request)
{
struct wiphy *wiphy = rtwdev->hw->wiphy;
next_regd->state = RTW_REGD_STATE_WORLDWIDE;
if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
!rtw_reg_is_ww(next_regd->regulatory)) {
next_regd->state = RTW_REGD_STATE_SETTING;
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
}
return true;
}
static bool rtw_regd_mgmt_programmed(struct rtw_dev *rtwdev,
struct rtw_regd *next_regd,
struct regulatory_request *request)
{
if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
rtw_reg_match(next_regd->regulatory, rtwdev->efuse.country_code)) {
next_regd->state = RTW_REGD_STATE_PROGRAMMED;
return true;
}
return false;
}
static bool rtw_regd_mgmt_setting(struct rtw_dev *rtwdev,
struct rtw_regd *next_regd,
struct regulatory_request *request)
{
struct wiphy *wiphy = rtwdev->hw->wiphy;
if (request->initiator != NL80211_REGDOM_SET_BY_USER)
return false;
next_regd->state = RTW_REGD_STATE_SETTING;
if (rtw_reg_is_ww(next_regd->regulatory)) {
next_regd->state = RTW_REGD_STATE_WORLDWIDE;
wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
}
return true;
}
static bool (*const rtw_regd_handler[RTW_REGD_STATE_NR])
(struct rtw_dev *, struct rtw_regd *, struct regulatory_request *) = {
[RTW_REGD_STATE_WORLDWIDE] = rtw_regd_mgmt_worldwide,
[RTW_REGD_STATE_PROGRAMMED] = rtw_regd_mgmt_programmed,
[RTW_REGD_STATE_SETTING] = rtw_regd_mgmt_setting,
};
static bool rtw_regd_state_hdl(struct rtw_dev *rtwdev,
struct rtw_regd *next_regd,
struct regulatory_request *request)
{
next_regd->regulatory = rtw_reg_find_by_name(request->alpha2);
next_regd->dfs_region = request->dfs_region;
return rtw_regd_handler[rtwdev->regd.state](rtwdev, next_regd, request);
}
static
void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct rtw_dev *rtwdev = hw->priv;
struct rtw_hal *hal = &rtwdev->hal;
struct rtw_regd next_regd = {0};
bool hdl;
hdl = rtw_regd_state_hdl(rtwdev, &next_regd, request);
if (!hdl) {
rtw_dbg(rtwdev, RTW_DBG_REGD,
"regd state %d: ignore request %c%c of initiator %d\n",
rtwdev->regd.state,
request->alpha2[0],
request->alpha2[1],
request->initiator);
return;
}
rtw_dbg(rtwdev, RTW_DBG_REGD, "regd state: %d -> %d\n",
rtwdev->regd.state, next_regd.state);
rtwdev->regd = next_regd;
rtw_dbg_regd_dump(rtwdev, "get alpha2 %c%c from initiator %d: ",
request->alpha2[0],
request->alpha2[1],
request->initiator);
rtw_phy_adaptivity_set_mode(rtwdev);
rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
}
u8 rtw_regd_get(struct rtw_dev *rtwdev)
{
struct rtw_hal *hal = &rtwdev->hal;
u8 band = hal->current_band_type;
return band == RTW_BAND_2G ?
rtwdev->regd.regulatory->txpwr_regd_2g :
rtwdev->regd.regulatory->txpwr_regd_5g;
}
EXPORT_SYMBOL(rtw_regd_get);
struct rtw_regd_alternative_t {
bool set;
u8 alt;
};
#define DECL_REGD_ALT(_regd, _regd_alt) \
[(_regd)] = {.set = true, .alt = (_regd_alt)}
static const struct rtw_regd_alternative_t
rtw_regd_alt[RTW_REGD_MAX] = {
DECL_REGD_ALT(RTW_REGD_IC, RTW_REGD_FCC),
DECL_REGD_ALT(RTW_REGD_KCC, RTW_REGD_ETSI),
DECL_REGD_ALT(RTW_REGD_ACMA, RTW_REGD_ETSI),
DECL_REGD_ALT(RTW_REGD_CHILE, RTW_REGD_FCC),
DECL_REGD_ALT(RTW_REGD_UKRAINE, RTW_REGD_ETSI),
DECL_REGD_ALT(RTW_REGD_MEXICO, RTW_REGD_FCC),
DECL_REGD_ALT(RTW_REGD_CN, RTW_REGD_ETSI),
};
bool rtw_regd_has_alt(u8 regd, u8 *regd_alt)
{
if (!rtw_regd_alt[regd].set)
return false;
*regd_alt = rtw_regd_alt[regd].alt;
return true;
}

View File

@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_REGD_H_
#define __RTW_REGD_H_
#define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR
#define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR
enum rtw_chplan_id {
RTW_CHPLAN_ETSI1_NULL = 0x21,
RTW_CHPLAN_WORLD_ETSI1 = 0x26,
RTW_CHPLAN_MKK1_MKK1 = 0x27,
RTW_CHPLAN_IC1_IC2 = 0x2B,
RTW_CHPLAN_WORLD_CHILE1 = 0x2D,
RTW_CHPLAN_WORLD_FCC3 = 0x30,
RTW_CHPLAN_WORLD_FCC5 = 0x32,
RTW_CHPLAN_FCC1_FCC7 = 0x34,
RTW_CHPLAN_WORLD_ETSI2 = 0x35,
RTW_CHPLAN_WORLD_ETSI3 = 0x36,
RTW_CHPLAN_ETSI1_ETSI12 = 0x3D,
RTW_CHPLAN_KCC1_KCC2 = 0x3E,
RTW_CHPLAN_ETSI1_ETSI4 = 0x42,
RTW_CHPLAN_FCC1_NCC3 = 0x44,
RTW_CHPLAN_WORLD_ACMA1 = 0x45,
RTW_CHPLAN_WORLD_ETSI6 = 0x47,
RTW_CHPLAN_WORLD_ETSI7 = 0x48,
RTW_CHPLAN_WORLD_ETSI8 = 0x49,
RTW_CHPLAN_KCC1_KCC3 = 0x4B,
RTW_CHPLAN_WORLD_ETSI10 = 0x51,
RTW_CHPLAN_WORLD_ETSI14 = 0x59,
RTW_CHPLAN_FCC2_FCC7 = 0x61,
RTW_CHPLAN_FCC2_FCC1 = 0x62,
RTW_CHPLAN_WORLD_ETSI15 = 0x63,
RTW_CHPLAN_WORLD_FCC7 = 0x73,
RTW_CHPLAN_FCC2_FCC17 = 0x74,
RTW_CHPLAN_WORLD_ETSI20 = 0x75,
RTW_CHPLAN_FCC2_FCC11 = 0x76,
RTW_CHPLAN_REALTEK_DEFINE = 0x7f,
};
struct country_code_to_enum_rd {
u16 countrycode;
const char *iso_name;
};
enum country_code_type {
COUNTRY_CODE_FCC = 0,
COUNTRY_CODE_IC = 1,
COUNTRY_CODE_ETSI = 2,
COUNTRY_CODE_SPAIN = 3,
COUNTRY_CODE_FRANCE = 4,
COUNTRY_CODE_MKK = 5,
COUNTRY_CODE_MKK1 = 6,
COUNTRY_CODE_ISRAEL = 7,
COUNTRY_CODE_TELEC = 8,
COUNTRY_CODE_MIC = 9,
COUNTRY_CODE_GLOBAL_DOMAIN = 10,
COUNTRY_CODE_WORLD_WIDE_13 = 11,
COUNTRY_CODE_TELEC_NETGEAR = 12,
COUNTRY_CODE_WORLD_WIDE_13_5G_ALL = 13,
/* new channel plan above this */
COUNTRY_CODE_MAX
};
int rtw_regd_init(struct rtw_dev *rtwdev);
int rtw_regd_hint(struct rtw_dev *rtwdev);
u8 rtw_regd_get(struct rtw_dev *rtwdev);
bool rtw_regd_has_alt(u8 regd, u8 *regd_alt);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,286 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8723D_H__
#define __RTW8723D_H__
enum rtw8723d_path {
PATH_S1,
PATH_S0,
PATH_NR,
};
enum rtw8723d_iqk_round {
IQK_ROUND_0,
IQK_ROUND_1,
IQK_ROUND_2,
IQK_ROUND_HYBRID,
IQK_ROUND_SIZE,
IQK_ROUND_INVALID = 0xff,
};
enum rtw8723d_iqk_result {
IQK_S1_TX_X,
IQK_S1_TX_Y,
IQK_S1_RX_X,
IQK_S1_RX_Y,
IQK_S0_TX_X,
IQK_S0_TX_Y,
IQK_S0_RX_X,
IQK_S0_RX_Y,
IQK_NR,
IQK_SX_NR = IQK_NR / PATH_NR,
};
struct rtw8723de_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vender_id[2];
u8 device_id[2];
u8 sub_vender_id[2];
u8 sub_device_id[2];
};
struct rtw8723d_efuse {
__le16 rtl_id;
u8 rsvd[2];
u8 afe;
u8 rsvd1[11];
/* power index for four RF paths */
struct rtw_txpwr_idx txpwr_idx_table[4];
u8 channel_plan; /* 0xb8 */
u8 xtal_k;
u8 thermal_meter;
u8 iqk_lck;
u8 pa_type; /* 0xbc */
u8 lna_type_2g[2]; /* 0xbd */
u8 lna_type_5g[2];
u8 rf_board_option;
u8 rf_feature_option;
u8 rf_bt_setting;
u8 eeprom_version;
u8 eeprom_customer_id;
u8 tx_bb_swing_setting_2g;
u8 res_c7;
u8 tx_pwr_calibrate_rate;
u8 rf_antenna_option; /* 0xc9 */
u8 rfe_option;
u8 country_code[2];
u8 res[3];
struct rtw8723de_efuse e;
};
/* phy status page0 */
#define GET_PHY_STAT_P0_PWDB(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
/* phy status page1 */
#define GET_PHY_STAT_P1_PWDB_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
#define GET_PHY_STAT_P1_PWDB_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(23, 16))
#define GET_PHY_STAT_P1_RF_MODE(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(29, 28))
#define GET_PHY_STAT_P1_L_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
#define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
static inline s32 iqkxy_to_s32(s32 val)
{
/* val is Q10.8 */
return sign_extend32(val, 9);
}
static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
{
/* x, y and return value are Q10.8 */
s32 t;
t = x * y;
if (ext)
*ext = (t >> 7) & 0x1; /* Q.16 --> Q.9; get LSB of Q.9 */
return (t >> 8); /* Q.16 --> Q.8 */
}
#define OFDM_SWING_A(swing) FIELD_GET(GENMASK(9, 0), swing)
#define OFDM_SWING_B(swing) FIELD_GET(GENMASK(15, 10), swing)
#define OFDM_SWING_C(swing) FIELD_GET(GENMASK(21, 16), swing)
#define OFDM_SWING_D(swing) FIELD_GET(GENMASK(31, 22), swing)
#define RTW_DEF_OFDM_SWING_INDEX 28
#define RTW_DEF_CCK_SWING_INDEX 28
#define MAX_TOLERANCE 5
#define IQK_TX_X_ERR 0x142
#define IQK_TX_Y_ERR 0x42
#define IQK_RX_X_UPPER 0x11a
#define IQK_RX_X_LOWER 0xe6
#define IQK_RX_Y_LMT 0x1a
#define IQK_TX_OK BIT(0)
#define IQK_RX_OK BIT(1)
#define PATH_IQK_RETRY 2
#define SPUR_THRES 0x16
#define CCK_DFIR_NR 3
#define DIS_3WIRE 0xccf000c0
#define EN_3WIRE 0xccc000c0
#define START_PSD 0x400000
#define FREQ_CH13 0xfccd
#define FREQ_CH14 0xff9a
#define RFCFGCH_CHANNEL_MASK GENMASK(7, 0)
#define RFCFGCH_BW_MASK (BIT(11) | BIT(10))
#define RFCFGCH_BW_20M (BIT(11) | BIT(10))
#define RFCFGCH_BW_40M BIT(10)
#define BIT_MASK_RFMOD BIT(0)
#define BIT_LCK BIT(15)
#define REG_GPIO_INTM 0x0048
#define REG_BTG_SEL 0x0067
#define BIT_MASK_BTG_WL BIT(7)
#define REG_LTECOEX_PATH_CONTROL 0x0070
#define REG_LTECOEX_CTRL 0x07c0
#define REG_LTECOEX_WRITE_DATA 0x07c4
#define REG_LTECOEX_READ_DATA 0x07c8
#define REG_PSDFN 0x0808
#define REG_BB_PWR_SAV1_11N 0x0874
#define REG_ANA_PARAM1 0x0880
#define REG_ANALOG_P4 0x088c
#define REG_PSDRPT 0x08b4
#define REG_FPGA1_RFMOD 0x0900
#define REG_BB_SEL_BTG 0x0948
#define REG_BBRX_DFIR 0x0954
#define BIT_MASK_RXBB_DFIR GENMASK(27, 24)
#define BIT_RXBB_DFIR_EN BIT(19)
#define REG_CCK0_SYS 0x0a00
#define BIT_CCK_SIDE_BAND BIT(4)
#define REG_CCK_ANT_SEL_11N 0x0a04
#define REG_PWRTH 0x0a08
#define REG_CCK_FA_RST_11N 0x0a2c
#define BIT_MASK_CCK_CNT_KEEP BIT(12)
#define BIT_MASK_CCK_CNT_EN BIT(13)
#define BIT_MASK_CCK_CNT_KPEN (BIT_MASK_CCK_CNT_KEEP | BIT_MASK_CCK_CNT_EN)
#define BIT_MASK_CCK_FA_KEEP BIT(14)
#define BIT_MASK_CCK_FA_EN BIT(15)
#define BIT_MASK_CCK_FA_KPEN (BIT_MASK_CCK_FA_KEEP | BIT_MASK_CCK_FA_EN)
#define REG_CCK_FA_LSB_11N 0x0a5c
#define REG_CCK_FA_MSB_11N 0x0a58
#define REG_CCK_CCA_CNT_11N 0x0a60
#define BIT_MASK_CCK_FA_MSB GENMASK(7, 0)
#define BIT_MASK_CCK_FA_LSB GENMASK(15, 8)
#define REG_PWRTH2 0x0aa8
#define REG_CSRATIO 0x0aaa
#define REG_OFDM_FA_HOLDC_11N 0x0c00
#define BIT_MASK_OFDM_FA_KEEP BIT(31)
#define REG_BB_RX_PATH_11N 0x0c04
#define REG_TRMUX_11N 0x0c08
#define REG_OFDM_FA_RSTC_11N 0x0c0c
#define BIT_MASK_OFDM_FA_RST BIT(31)
#define REG_A_RXIQI 0x0c14
#define BIT_MASK_RXIQ_S1_X 0x000003FF
#define BIT_MASK_RXIQ_S1_Y1 0x0000FC00
#define BIT_SET_RXIQ_S1_Y1(y) ((y) & 0x3F)
#define REG_OFDM0_RXDSP 0x0c40
#define BIT_MASK_RXDSP GENMASK(28, 24)
#define BIT_EN_RXDSP BIT(9)
#define REG_OFDM_0_ECCA_THRESHOLD 0x0c4c
#define BIT_MASK_OFDM0_EXT_A BIT(31)
#define BIT_MASK_OFDM0_EXT_C BIT(29)
#define BIT_MASK_OFDM0_EXTS (BIT(31) | BIT(29) | BIT(28))
#define BIT_SET_OFDM0_EXTS(a, c, d) (((a) << 31) | ((c) << 29) | ((d) << 28))
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58
#define REG_AGCRSSI 0x0c78
#define REG_OFDM_0_XA_TX_IQ_IMBALANCE 0x0c80
#define BIT_MASK_TXIQ_ELM_A 0x03ff
#define BIT_SET_TXIQ_ELM_ACD(a, c, d) (((d) << 22) | (((c) & 0x3F) << 16) | \
((a) & 0x03ff))
#define BIT_MASK_TXIQ_ELM_C GENMASK(21, 16)
#define BIT_SET_TXIQ_ELM_C2(c) ((c) & 0x3F)
#define BIT_MASK_TXIQ_ELM_D GENMASK(31, 22)
#define REG_TXIQK_MATRIXA_LSB2_11N 0x0c94
#define BIT_SET_TXIQ_ELM_C1(c) (((c) & 0x000003C0) >> 6)
#define REG_RXIQK_MATRIX_LSB_11N 0x0ca0
#define BIT_MASK_RXIQ_S1_Y2 0xF0000000
#define BIT_SET_RXIQ_S1_Y2(y) (((y) >> 6) & 0xF)
#define REG_TXIQ_AB_S0 0x0cd0
#define BIT_MASK_TXIQ_A_S0 0x000007FE
#define BIT_MASK_TXIQ_A_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_B_S0 0x0007E000
#define REG_TXIQ_CD_S0 0x0cd4
#define BIT_MASK_TXIQ_C_S0 0x000007FE
#define BIT_MASK_TXIQ_C_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_D_S0 GENMASK(22, 13)
#define BIT_MASK_TXIQ_D_EXT_S0 BIT(12)
#define REG_RXIQ_AB_S0 0x0cd8
#define BIT_MASK_RXIQ_X_S0 0x000003FF
#define BIT_MASK_RXIQ_Y_S0 0x003FF000
#define REG_OFDM_FA_TYPE1_11N 0x0cf0
#define BIT_MASK_OFDM_FF_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_SF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_RSTD_11N 0x0d00
#define BIT_MASK_OFDM_FA_RST1 BIT(27)
#define BIT_MASK_OFDM_FA_KEEP1 BIT(31)
#define REG_CTX 0x0d03
#define BIT_MASK_CTX_TYPE GENMASK(6, 4)
#define REG_OFDM1_CFOTRK 0x0d2c
#define BIT_EN_CFOTRK BIT(28)
#define REG_OFDM1_CSI1 0x0d40
#define REG_OFDM1_CSI2 0x0d44
#define REG_OFDM1_CSI3 0x0d48
#define REG_OFDM1_CSI4 0x0d4c
#define REG_OFDM_FA_TYPE2_11N 0x0da0
#define BIT_MASK_OFDM_CCA_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_PF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE3_11N 0x0da4
#define BIT_MASK_OFDM_RI_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_CRC_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE4_11N 0x0da8
#define BIT_MASK_OFDM_MNS_CNT GENMASK(15, 0)
#define REG_FPGA0_IQK_11N 0x0e28
#define BIT_MASK_IQK_MOD 0xffffff00
#define EN_IQK 0x808000
#define RST_IQK 0x000000
#define REG_TXIQK_TONE_A_11N 0x0e30
#define REG_RXIQK_TONE_A_11N 0x0e34
#define REG_TXIQK_PI_A_11N 0x0e38
#define REG_RXIQK_PI_A_11N 0x0e3c
#define REG_TXIQK_11N 0x0e40
#define BIT_SET_TXIQK_11N(x, y) (0x80007C00 | ((x) << 16) | (y))
#define REG_RXIQK_11N 0x0e44
#define REG_IQK_AGC_PTS_11N 0x0e48
#define REG_IQK_AGC_RSP_11N 0x0e4c
#define REG_TX_IQK_TONE_B 0x0e50
#define REG_RX_IQK_TONE_B 0x0e54
#define REG_IQK_RES_TX 0x0e94
#define BIT_MASK_RES_TX GENMASK(25, 16)
#define REG_IQK_RES_TY 0x0e9c
#define BIT_MASK_RES_TY GENMASK(25, 16)
#define REG_IQK_RES_RX 0x0ea4
#define BIT_MASK_RES_RX GENMASK(25, 16)
#define REG_IQK_RES_RY 0x0eac
#define BIT_IQK_TX_FAIL BIT(28)
#define BIT_IQK_RX_FAIL BIT(27)
#define BIT_IQK_DONE BIT(26)
#define BIT_MASK_RES_RY GENMASK(25, 16)
#define REG_PAGE_F_RST_11N 0x0f14
#define BIT_MASK_F_RST_ALL BIT(16)
#define REG_IGI_C_11N 0x0f84
#define REG_IGI_D_11N 0x0f88
#define REG_HT_CRC32_CNT_11N 0x0f90
#define BIT_MASK_HT_CRC_OK GENMASK(15, 0)
#define BIT_MASK_HT_CRC_ERR GENMASK(31, 16)
#define REG_OFDM_CRC32_CNT_11N 0x0f94
#define BIT_MASK_OFDM_LCRC_OK GENMASK(15, 0)
#define BIT_MASK_OFDM_LCRC_ERR GENMASK(31, 16)
#define REG_HT_CRC32_CNT_11N_AGG 0x0fb8
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8723D_TABLE_H__
#define __RTW8723D_TABLE_H__
extern const struct rtw_table rtw8723d_mac_tbl;
extern const struct rtw_table rtw8723d_agc_tbl;
extern const struct rtw_table rtw8723d_bb_tbl;
extern const struct rtw_table rtw8723d_bb_pg_tbl;
extern const struct rtw_table rtw8723d_rf_a_tbl;
extern const struct rtw_table rtw8723d_txpwr_lmt_tbl;
#endif

View File

@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
#include "rtw8723de.h"
static const struct pci_device_id rtw_8723de_id_table[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xD723),
.driver_data = (kernel_ulong_t)&rtw8723d_hw_spec
},
{}
};
MODULE_DEVICE_TABLE(pci, rtw_8723de_id_table);
static struct pci_driver rtw_8723de_driver = {
.name = "rtw_8723de",
.id_table = rtw_8723de_id_table,
.probe = rtw_pci_probe,
.remove = rtw_pci_remove,
.driver.pm = &rtw_pm_ops,
.shutdown = rtw_pci_shutdown,
#if defined(__FreeBSD__)
.bsddriver.name = KBUILD_MODNAME,
#endif
};
module_pci_driver(rtw_8723de_driver);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11n wireless 8723de driver");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_8723DE_H_
#define __RTW_8723DE_H_
extern struct rtw_chip_info rtw8723d_hw_spec;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,279 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8821C_H__
#define __RTW8821C_H__
#include <asm/byteorder.h>
#define RCR_VHT_ACK BIT(26)
struct rtw8821ce_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vender_id[2];
u8 device_id[2];
u8 sub_vender_id[2];
u8 sub_device_id[2];
u8 pmc[2];
u8 exp_device_cap[2];
u8 msi_cap;
u8 ltr_cap; /* 0xe3 */
u8 exp_link_control[2];
u8 link_cap[4];
u8 link_control[2];
u8 serial_number[8];
u8 res0:2; /* 0xf4 */
u8 ltr_en:1;
u8 res1:2;
u8 obff:2;
u8 res2:3;
u8 obff_cap:2;
u8 res3:4;
u8 res4[3];
u8 class_code[3];
u8 pci_pm_L1_2_supp:1;
u8 pci_pm_L1_1_supp:1;
u8 aspm_pm_L1_2_supp:1;
u8 aspm_pm_L1_1_supp:1;
u8 L1_pm_substates_supp:1;
u8 res5:3;
u8 port_common_mode_restore_time;
u8 port_t_power_on_scale:2;
u8 res6:1;
u8 port_t_power_on_value:5;
u8 res7;
};
struct rtw8821c_efuse {
__le16 rtl_id;
u8 res0[0x0e];
/* power index for four RF paths */
struct rtw_txpwr_idx txpwr_idx_table[4];
u8 channel_plan; /* 0xb8 */
u8 xtal_k;
u8 thermal_meter;
u8 iqk_lck;
u8 pa_type; /* 0xbc */
u8 lna_type_2g[2]; /* 0xbd */
u8 lna_type_5g[2];
u8 rf_board_option;
u8 rf_feature_option;
u8 rf_bt_setting;
u8 eeprom_version;
u8 eeprom_customer_id;
u8 tx_bb_swing_setting_2g;
u8 tx_bb_swing_setting_5g;
u8 tx_pwr_calibrate_rate;
u8 rf_antenna_option; /* 0xc9 */
u8 rfe_option;
u8 country_code[2];
u8 res[3];
union {
struct rtw8821ce_efuse e;
};
};
static inline void
_rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
{
/* 0xC00-0xCFF and 0xE00-0xEFF have the same layout */
rtw_write32_mask(rtwdev, addr, mask, data);
rtw_write32_mask(rtwdev, addr + 0x200, mask, data);
}
#define rtw_write32s_mask(rtwdev, addr, mask, data) \
do { \
BUILD_BUG_ON((addr) < 0xC00 || (addr) >= 0xD00); \
\
_rtw_write32s_mask(rtwdev, addr, mask, data); \
} while (0)
#define BIT_FEN_PCIEA BIT(6)
#define WLAN_SLOT_TIME 0x09
#define WLAN_PIFS_TIME 0x19
#define WLAN_SIFS_CCK_CONT_TX 0xA
#define WLAN_SIFS_OFDM_CONT_TX 0xE
#define WLAN_SIFS_CCK_TRX 0x10
#define WLAN_SIFS_OFDM_TRX 0x10
#define WLAN_VO_TXOP_LIMIT 0x186
#define WLAN_VI_TXOP_LIMIT 0x3BC
#define WLAN_RDG_NAV 0x05
#define WLAN_TXOP_NAV 0x1B
#define WLAN_CCK_RX_TSF 0x30
#define WLAN_OFDM_RX_TSF 0x30
#define WLAN_TBTT_PROHIBIT 0x04
#define WLAN_TBTT_HOLD_TIME 0x064
#define WLAN_DRV_EARLY_INT 0x04
#define WLAN_BCN_DMA_TIME 0x02
#define WLAN_RX_FILTER0 0x0FFFFFFF
#define WLAN_RX_FILTER2 0xFFFF
#define WLAN_RCR_CFG 0xE400220E
#define WLAN_RXPKT_MAX_SZ 12288
#define WLAN_RXPKT_MAX_SZ_512 (WLAN_RXPKT_MAX_SZ >> 9)
#define WLAN_AMPDU_MAX_TIME 0x70
#define WLAN_RTS_LEN_TH 0xFF
#define WLAN_RTS_TX_TIME_TH 0x08
#define WLAN_MAX_AGG_PKT_LIMIT 0x20
#define WLAN_RTS_MAX_AGG_PKT_LIMIT 0x20
#define FAST_EDCA_VO_TH 0x06
#define FAST_EDCA_VI_TH 0x06
#define FAST_EDCA_BE_TH 0x06
#define FAST_EDCA_BK_TH 0x06
#define WLAN_BAR_RETRY_LIMIT 0x01
#define WLAN_RA_TRY_RATE_AGG_LIMIT 0x08
#define WLAN_TX_FUNC_CFG1 0x30
#define WLAN_TX_FUNC_CFG2 0x30
#define WLAN_MAC_OPT_NORM_FUNC1 0x98
#define WLAN_MAC_OPT_LB_FUNC1 0x80
#define WLAN_MAC_OPT_FUNC2 0xb0810041
#define WLAN_SIFS_CFG (WLAN_SIFS_CCK_CONT_TX | \
(WLAN_SIFS_OFDM_CONT_TX << BIT_SHIFT_SIFS_OFDM_CTX) | \
(WLAN_SIFS_CCK_TRX << BIT_SHIFT_SIFS_CCK_TRX) | \
(WLAN_SIFS_OFDM_TRX << BIT_SHIFT_SIFS_OFDM_TRX))
#define WLAN_TBTT_TIME (WLAN_TBTT_PROHIBIT |\
(WLAN_TBTT_HOLD_TIME << BIT_SHIFT_TBTT_HOLD_TIME_AP))
#define WLAN_NAV_CFG (WLAN_RDG_NAV | (WLAN_TXOP_NAV << 16))
#define WLAN_RX_TSF_CFG (WLAN_CCK_RX_TSF | (WLAN_OFDM_RX_TSF) << 8)
#define WLAN_PRE_TXCNT_TIME_TH 0x1E4
/* phy status page0 */
#define GET_PHY_STAT_P0_PWDB(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
#define GET_PHY_STAT_P0_VGA(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(12, 8))
#define GET_PHY_STAT_P0_LNA_L(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(15, 13))
#define GET_PHY_STAT_P0_LNA_H(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x03), BIT(23))
#define BIT_LNA_H_MASK BIT(3)
#define BIT_LNA_L_MASK GENMASK(2, 0)
/* phy status page1 */
#define GET_PHY_STAT_P1_PWDB_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
#define GET_PHY_STAT_P1_PWDB_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(23, 16))
#define GET_PHY_STAT_P1_RF_MODE(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(29, 28))
#define GET_PHY_STAT_P1_L_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
#define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXEVM_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(15, 8))
#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
#define GET_PHY_STAT_P1_CFO_TAIL_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(15, 8))
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXSNR_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8))
#define REG_SYS_CTRL 0x000
#define BIT_FEN_EN BIT(26)
#define REG_INIRTS_RATE_SEL 0x0480
#define REG_HTSTFWT 0x800
#define REG_RXPSEL 0x808
#define BIT_RX_PSEL_RST (BIT(28) | BIT(29))
#define REG_TXPSEL 0x80c
#define REG_RXCCAMSK 0x814
#define REG_CCASEL 0x82c
#define REG_PDMFTH 0x830
#define REG_CCA2ND 0x838
#define REG_L1WT 0x83c
#define REG_L1PKWT 0x840
#define REG_MRC 0x850
#define REG_CLKTRK 0x860
#define REG_ADCCLK 0x8ac
#define REG_ADC160 0x8c4
#define REG_ADC40 0x8c8
#define REG_CHFIR 0x8f0
#define REG_CDDTXP 0x93c
#define REG_TXPSEL1 0x940
#define REG_ACBB0 0x948
#define REG_ACBBRXFIR 0x94c
#define REG_ACGG2TBL 0x958
#define REG_FAS 0x9a4
#define REG_RXSB 0xa00
#define REG_ADCINI 0xa04
#define REG_PWRTH 0xa08
#define REG_TXSF2 0xa24
#define REG_TXSF6 0xa28
#define REG_FA_CCK 0xa5c
#define REG_RXDESC 0xa2c
#define REG_ENTXCCK 0xa80
#define BTG_LNA 0xfc84
#define WLG_LNA 0x7532
#define REG_ENRXCCA 0xa84
#define BTG_CCA 0x0e
#define WLG_CCA 0x12
#define REG_PWRTH2 0xaa8
#define REG_CSRATIO 0xaaa
#define REG_TXFILTER 0xaac
#define REG_CNTRST 0xb58
#define REG_AGCTR_A 0xc08
#define REG_TXSCALE_A 0xc1c
#define REG_TXDFIR 0xc20
#define REG_RXIGI_A 0xc50
#define REG_TXAGCIDX 0xc94
#define REG_TRSW 0xca0
#define REG_RFESEL0 0xcb0
#define REG_RFESEL8 0xcb4
#define REG_RFECTL 0xcb8
#define B_BTG_SWITCH BIT(16)
#define B_CTRL_SWITCH BIT(18)
#define B_WL_SWITCH (BIT(20) | BIT(22))
#define B_WLG_SWITCH BIT(21)
#define B_WLA_SWITCH BIT(23)
#define REG_RFEINV 0xcbc
#define REG_AGCTR_B 0xe08
#define REG_RXIGI_B 0xe50
#define REG_CRC_CCK 0xf04
#define REG_CRC_OFDM 0xf14
#define REG_CRC_HT 0xf10
#define REG_CRC_VHT 0xf0c
#define REG_CCA_OFDM 0xf08
#define REG_FA_OFDM 0xf48
#define REG_CCA_CCK 0xfcc
#define REG_DMEM_CTRL 0x1080
#define BIT_WL_RST BIT(16)
#define REG_ANTWT 0x1904
#define REG_IQKFAILMSK 0x1bf0
#define BIT_MASK_R_RFE_SEL_15 GENMASK(31, 28)
#define BIT_SDIO_INT BIT(18)
#define BT_CNT_ENABLE 0x1
#define BIT_BCN_QUEUE BIT(3)
#define BCN_PRI_EN 0x1
#define PTA_CTRL_PIN 0x66
#define DPDT_CTRL_PIN 0x77
#define ANTDIC_CTRL_PIN 0x88
#define REG_CTRL_TYPE 0x67
#define BIT_CTRL_TYPE1 BIT(5)
#define BIT_CTRL_TYPE2 BIT(4)
#define CTRL_TYPE_MASK GENMASK(15, 8)
#define RF18_BAND_MASK (BIT(16) | BIT(9) | BIT(8))
#define RF18_BAND_2G (0)
#define RF18_BAND_5G (BIT(16) | BIT(8))
#define RF18_CHANNEL_MASK (MASKBYTE0)
#define RF18_RFSI_MASK (BIT(18) | BIT(17))
#define RF18_RFSI_GE (BIT(17))
#define RF18_RFSI_GT (BIT(18))
#define RF18_BW_MASK (BIT(11) | BIT(10))
#define RF18_BW_20M (BIT(11) | BIT(10))
#define RF18_BW_40M (BIT(11))
#define RF18_BW_80M (BIT(10))
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8821C_TABLE_H__
#define __RTW8821C_TABLE_H__
extern const struct rtw_table rtw8821c_mac_tbl;
extern const struct rtw_table rtw8821c_agc_tbl;
extern const struct rtw_table rtw8821c_agc_btg_type2_tbl;
extern const struct rtw_table rtw8821c_bb_tbl;
extern const struct rtw_table rtw8821c_bb_pg_type0_tbl;
extern const struct rtw_table rtw8821c_rf_a_tbl;
extern const struct rtw_table rtw8821c_txpwr_lmt_type0_tbl;
#endif

View File

@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
#include "rtw8821ce.h"
static const struct pci_device_id rtw_8821ce_id_table[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC821),
.driver_data = (kernel_ulong_t)&rtw8821c_hw_spec
},
{}
};
MODULE_DEVICE_TABLE(pci, rtw_8821ce_id_table);
static struct pci_driver rtw_8821ce_driver = {
.name = "rtw_8821ce",
.id_table = rtw_8821ce_id_table,
.probe = rtw_pci_probe,
.remove = rtw_pci_remove,
.driver.pm = &rtw_pm_ops,
.shutdown = rtw_pci_shutdown,
#if defined(__FreeBSD__)
.bsddriver.name = KBUILD_MODNAME,
#endif
};
module_pci_driver(rtw_8821ce_driver);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821ce driver");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_8821CE_H_
#define __RTW_8821CE_H_
extern struct rtw_chip_info rtw8821c_hw_spec;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,190 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8822B_H__
#define __RTW8822B_H__
#include <asm/byteorder.h>
#define RCR_VHT_ACK BIT(26)
struct rtw8822bu_efuse {
u8 res4[4]; /* 0xd0 */
u8 usb_optional_function;
u8 res5[0x1e];
u8 res6[2];
u8 serial[0x0b]; /* 0xf5 */
u8 vid; /* 0x100 */
u8 res7;
u8 pid;
u8 res8[4];
u8 mac_addr[ETH_ALEN]; /* 0x107 */
u8 res9[2];
u8 vendor_name[0x07];
u8 res10[2];
u8 device_name[0x14];
u8 res11[0xcf];
u8 package_type; /* 0x1fb */
u8 res12[0x4];
};
struct rtw8822be_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vender_id[2];
u8 device_id[2];
u8 sub_vender_id[2];
u8 sub_device_id[2];
u8 pmc[2];
u8 exp_device_cap[2];
u8 msi_cap;
u8 ltr_cap; /* 0xe3 */
u8 exp_link_control[2];
u8 link_cap[4];
u8 link_control[2];
u8 serial_number[8];
u8 res0:2; /* 0xf4 */
u8 ltr_en:1;
u8 res1:2;
u8 obff:2;
u8 res2:3;
u8 obff_cap:2;
u8 res3:4;
u8 res4[3];
u8 class_code[3];
u8 pci_pm_L1_2_supp:1;
u8 pci_pm_L1_1_supp:1;
u8 aspm_pm_L1_2_supp:1;
u8 aspm_pm_L1_1_supp:1;
u8 L1_pm_substates_supp:1;
u8 res5:3;
u8 port_common_mode_restore_time;
u8 port_t_power_on_scale:2;
u8 res6:1;
u8 port_t_power_on_value:5;
u8 res7;
};
struct rtw8822b_efuse {
__le16 rtl_id;
u8 res0[0x0e];
/* power index for four RF paths */
struct rtw_txpwr_idx txpwr_idx_table[4];
u8 channel_plan; /* 0xb8 */
u8 xtal_k;
u8 thermal_meter;
u8 iqk_lck;
u8 pa_type; /* 0xbc */
u8 lna_type_2g[2]; /* 0xbd */
u8 lna_type_5g[2];
u8 rf_board_option;
u8 rf_feature_option;
u8 rf_bt_setting;
u8 eeprom_version;
u8 eeprom_customer_id;
u8 tx_bb_swing_setting_2g;
u8 tx_bb_swing_setting_5g;
u8 tx_pwr_calibrate_rate;
u8 rf_antenna_option; /* 0xc9 */
u8 rfe_option;
u8 country_code[2];
u8 res[3];
union {
struct rtw8822bu_efuse u;
struct rtw8822be_efuse e;
};
};
static inline void
_rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
{
/* 0xC00-0xCFF and 0xE00-0xEFF have the same layout */
rtw_write32_mask(rtwdev, addr, mask, data);
rtw_write32_mask(rtwdev, addr + 0x200, mask, data);
}
#define rtw_write32s_mask(rtwdev, addr, mask, data) \
do { \
BUILD_BUG_ON((addr) < 0xC00 || (addr) >= 0xD00); \
\
_rtw_write32s_mask(rtwdev, addr, mask, data); \
} while (0)
/* phy status page0 */
#define GET_PHY_STAT_P0_PWDB(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
/* phy status page1 */
#define GET_PHY_STAT_P1_PWDB_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
#define GET_PHY_STAT_P1_PWDB_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(23, 16))
#define GET_PHY_STAT_P1_RF_MODE(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(29, 28))
#define GET_PHY_STAT_P1_L_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
#define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXEVM_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(15, 8))
#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
#define GET_PHY_STAT_P1_CFO_TAIL_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(15, 8))
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXSNR_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8))
#define RTW8822B_EDCCA_MAX 0x7f
#define RTW8822B_EDCCA_SRC_DEF 1
#define REG_HTSTFWT 0x800
#define REG_RXPSEL 0x808
#define BIT_RX_PSEL_RST (BIT(28) | BIT(29))
#define REG_TXPSEL 0x80c
#define REG_RXCCAMSK 0x814
#define REG_CCASEL 0x82c
#define REG_PDMFTH 0x830
#define REG_CCA2ND 0x838
#define REG_L1WT 0x83c
#define REG_L1PKWT 0x840
#define REG_MRC 0x850
#define REG_CLKTRK 0x860
#define REG_EDCCA_POW_MA 0x8a0
#define BIT_MA_LEVEL GENMASK(1, 0)
#define REG_ADCCLK 0x8ac
#define REG_ADC160 0x8c4
#define REG_ADC40 0x8c8
#define REG_EDCCA_DECISION 0x8dc
#define BIT_EDCCA_OPTION BIT(5)
#define REG_CDDTXP 0x93c
#define REG_TXPSEL1 0x940
#define REG_EDCCA_SOURCE 0x944
#define BIT_SOURCE_OPTION GENMASK(29, 28)
#define REG_ACBB0 0x948
#define REG_ACBBRXFIR 0x94c
#define REG_ACGG2TBL 0x958
#define REG_RXSB 0xa00
#define REG_ADCINI 0xa04
#define REG_TXSF2 0xa24
#define REG_TXSF6 0xa28
#define REG_RXDESC 0xa2c
#define REG_ENTXCCK 0xa80
#define REG_AGCTR_A 0xc08
#define REG_TXDFIR 0xc20
#define REG_RXIGI_A 0xc50
#define REG_TRSW 0xca0
#define REG_RFESEL0 0xcb0
#define REG_RFESEL8 0xcb4
#define REG_RFECTL 0xcb8
#define REG_RFEINV 0xcbc
#define REG_AGCTR_B 0xe08
#define REG_RXIGI_B 0xe50
#define REG_ANTWT 0x1904
#define REG_IQKFAILMSK 0x1bf0
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8822B_TABLE_H__
#define __RTW8822B_TABLE_H__
extern const struct rtw_table rtw8822b_mac_tbl;
extern const struct rtw_table rtw8822b_agc_tbl;
extern const struct rtw_table rtw8822b_bb_tbl;
extern const struct rtw_table rtw8822b_bb_pg_type2_tbl;
extern const struct rtw_table rtw8822b_bb_pg_type3_tbl;
extern const struct rtw_table rtw8822b_bb_pg_type5_tbl;
extern const struct rtw_table rtw8822b_rf_a_tbl;
extern const struct rtw_table rtw8822b_rf_b_tbl;
extern const struct rtw_table rtw8822b_txpwr_lmt_type0_tbl;
extern const struct rtw_table rtw8822b_txpwr_lmt_type2_tbl;
extern const struct rtw_table rtw8822b_txpwr_lmt_type5_tbl;
#endif

View File

@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
#include "rtw8822be.h"
static const struct pci_device_id rtw_8822be_id_table[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB822),
.driver_data = (kernel_ulong_t)&rtw8822b_hw_spec
},
{}
};
MODULE_DEVICE_TABLE(pci, rtw_8822be_id_table);
static struct pci_driver rtw_8822be_driver = {
.name = "rtw_8822be",
.id_table = rtw_8822be_id_table,
.probe = rtw_pci_probe,
.remove = rtw_pci_remove,
.driver.pm = &rtw_pm_ops,
.shutdown = rtw_pci_shutdown,
#if defined(__FreeBSD__)
.bsddriver.name = KBUILD_MODNAME,
#endif
};
module_pci_driver(rtw_8822be_driver);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822be driver");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_8822BE_H_
#define __RTW_8822BE_H_
extern struct rtw_chip_info rtw8822b_hw_spec;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,418 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8822C_H__
#define __RTW8822C_H__
#include <asm/byteorder.h>
struct rtw8822cu_efuse {
u8 res0[0x30]; /* 0x120 */
u8 vid[2]; /* 0x150 */
u8 pid[2];
u8 res1[3];
u8 mac_addr[ETH_ALEN]; /* 0x157 */
u8 res2[0x3d];
};
struct rtw8822ce_efuse {
u8 mac_addr[ETH_ALEN]; /* 0x120 */
u8 vender_id[2];
u8 device_id[2];
u8 sub_vender_id[2];
u8 sub_device_id[2];
u8 pmc[2];
u8 exp_device_cap[2];
u8 msi_cap;
u8 ltr_cap; /* 0x133 */
u8 exp_link_control[2];
u8 link_cap[4];
u8 link_control[2];
u8 serial_number[8];
u8 res0:2; /* 0x144 */
u8 ltr_en:1;
u8 res1:2;
u8 obff:2;
u8 res2:3;
u8 obff_cap:2;
u8 res3:4;
u8 class_code[3];
u8 res4;
u8 pci_pm_L1_2_supp:1;
u8 pci_pm_L1_1_supp:1;
u8 aspm_pm_L1_2_supp:1;
u8 aspm_pm_L1_1_supp:1;
u8 L1_pm_substates_supp:1;
u8 res5:3;
u8 port_common_mode_restore_time;
u8 port_t_power_on_scale:2;
u8 res6:1;
u8 port_t_power_on_value:5;
u8 res7;
};
struct rtw8822c_efuse {
__le16 rtl_id;
u8 res0[0x0e];
/* power index for four RF paths */
struct rtw_txpwr_idx txpwr_idx_table[4];
u8 channel_plan; /* 0xb8 */
u8 xtal_k;
u8 res1;
u8 iqk_lck;
u8 res2[5]; /* 0xbc */
u8 rf_board_option;
u8 rf_feature_option;
u8 rf_bt_setting;
u8 eeprom_version;
u8 eeprom_customer_id;
u8 tx_bb_swing_setting_2g;
u8 tx_bb_swing_setting_5g;
u8 tx_pwr_calibrate_rate;
u8 rf_antenna_option; /* 0xc9 */
u8 rfe_option;
u8 country_code[2];
u8 res3[3];
u8 path_a_thermal; /* 0xd0 */
u8 path_b_thermal;
u8 res4[2];
u8 rx_gain_gap_2g_ofdm;
u8 res5;
u8 rx_gain_gap_2g_cck;
u8 res6;
u8 rx_gain_gap_5gl;
u8 res7;
u8 rx_gain_gap_5gm;
u8 res8;
u8 rx_gain_gap_5gh;
u8 res9;
u8 res10[0x42];
union {
struct rtw8822cu_efuse u;
struct rtw8822ce_efuse e;
};
};
enum rtw8822c_dpk_agc_phase {
RTW_DPK_GAIN_CHECK,
RTW_DPK_GAIN_LARGE,
RTW_DPK_GAIN_LESS,
RTW_DPK_GL_LARGE,
RTW_DPK_GL_LESS,
RTW_DPK_LOSS_CHECK,
RTW_DPK_AGC_OUT,
};
enum rtw8822c_dpk_one_shot_action {
RTW_DPK_CAL_PWR,
RTW_DPK_GAIN_LOSS,
RTW_DPK_DO_DPK,
RTW_DPK_DPK_ON,
RTW_DPK_DAGC,
RTW_DPK_ACTION_MAX
};
void rtw8822c_parse_tbl_dpk(struct rtw_dev *rtwdev,
const struct rtw_table *tbl);
#define RTW_DECL_TABLE_DPK(name) \
const struct rtw_table name ## _tbl = { \
.data = name, \
.size = ARRAY_SIZE(name), \
.parse = rtw8822c_parse_tbl_dpk, \
}
#define DACK_PATH_8822C 2
#define DACK_REG_8822C 16
#define DACK_RF_8822C 1
#define DACK_SN_8822C 100
/* phy status page0 */
#define GET_PHY_STAT_P0_PWDB_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
#define GET_PHY_STAT_P0_PWDB_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P0_GAIN_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(21, 16))
#define GET_PHY_STAT_P0_CHANNEL(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(23, 16))
#define GET_PHY_STAT_P0_GAIN_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(29, 24))
/* phy status page1 */
#define GET_PHY_STAT_P1_PWDB_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
#define GET_PHY_STAT_P1_PWDB_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(23, 16))
#define GET_PHY_STAT_P1_L_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
#define GET_PHY_STAT_P1_CHANNEL(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(23, 16))
#define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXEVM_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(15, 8))
#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
#define GET_PHY_STAT_P1_CFO_TAIL_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(15, 8))
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXSNR_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8))
#define RTW8822C_EDCCA_MAX 0x7f
#define REG_ANAPARLDO_POW_MAC 0x0029
#define BIT_LDOE25_PON BIT(0)
#define XCAP_MASK GENMASK(6, 0)
#define CFO_TRK_ENABLE_TH 20
#define CFO_TRK_STOP_TH 10
#define CFO_TRK_ADJ_TH 10
#define REG_TXDFIR0 0x808
#define REG_DFIRBW 0x810
#define REG_ANTMAP0 0x820
#define BIT_ANT_PATH GENMASK(1, 0)
#define REG_ANTMAP 0x824
#define REG_EDCCA_DECISION 0x844
#define BIT_EDCCA_OPTION GENMASK(30, 29)
#define REG_DYMPRITH 0x86c
#define REG_DYMENTH0 0x870
#define REG_DYMENTH 0x874
#define REG_SBD 0x88c
#define BITS_SUBTUNE GENMASK(15, 12)
#define REG_DYMTHMIN 0x8a4
#define REG_TXBWCTL 0x9b0
#define REG_TXCLK 0x9b4
#define REG_SCOTRK 0xc30
#define REG_MRCM 0xc38
#define REG_AGCSWSH 0xc44
#define REG_ANTWTPD 0xc54
#define REG_PT_CHSMO 0xcbc
#define BIT_PT_OPT BIT(21)
#define REG_ORITXCODE 0x1800
#define BIT_PATH_EN BIT(31)
#define REG_3WIRE 0x180c
#define BIT_DIS_SHARERX_TXGAT BIT(27)
#define BIT_3WIRE_TX_EN BIT(0)
#define BIT_3WIRE_RX_EN BIT(1)
#define BIT_3WIRE_EN GENMASK(1, 0)
#define BIT_3WIRE_PI_ON BIT(28)
#define REG_ANAPAR_A 0x1830
#define BIT_ANAPAR_UPDATE BIT(29)
#define REG_RFTXEN_GCK_A 0x1864
#define BIT_RFTXEN_GCK_FORCE_ON BIT(31)
#define REG_DIS_SHARE_RX_A 0x186c
#define BIT_TX_SCALE_0DB BIT(7)
#define REG_RXAGCCTL0 0x18ac
#define BITS_RXAGC_CCK GENMASK(15, 12)
#define BITS_RXAGC_OFDM GENMASK(8, 4)
#define REG_DCKA_I_0 0x18bc
#define REG_DCKA_I_1 0x18c0
#define REG_DCKA_Q_0 0x18d8
#define REG_DCKA_Q_1 0x18dc
#define REG_CCKSB 0x1a00
#define BIT_BBMODE GENMASK(2, 1)
#define REG_RXCCKSEL 0x1a04
#define REG_BGCTRL 0x1a14
#define BITS_RX_IQ_WEIGHT (BIT(8) | BIT(9))
#define REG_TXF0 0x1a20
#define REG_TXF1 0x1a24
#define REG_TXF2 0x1a28
#define REG_CCANRX 0x1a2c
#define BIT_CCK_FA_RST (BIT(14) | BIT(15))
#define BIT_OFDM_FA_RST (BIT(12) | BIT(13))
#define REG_CCK_FACNT 0x1a5c
#define REG_CCKTXONLY 0x1a80
#define BIT_BB_CCK_CHECK_EN BIT(18)
#define REG_TXF3 0x1a98
#define REG_TXF4 0x1a9c
#define REG_TXF5 0x1aa0
#define REG_TXF6 0x1aac
#define REG_TXF7 0x1ab0
#define REG_CCK_SOURCE 0x1abc
#define BIT_NBI_EN BIT(30)
#define REG_NCTL0 0x1b00
#define BIT_SEL_PATH GENMASK(2, 1)
#define BIT_SUBPAGE GENMASK(3, 0)
#define REG_DPD_CTL0_S0 0x1b04
#define BIT_GS_PWSF GENMASK(27, 0)
#define REG_DPD_CTL1_S0 0x1b08
#define BIT_DPD_EN BIT(31)
#define BIT_PS_EN BIT(7)
#define REG_IQKSTAT 0x1b10
#define REG_IQK_CTL1 0x1b20
#define BIT_TX_CFIR GENMASK(31, 30)
#define BIT_CFIR_EN GENMASK(26, 24)
#define BIT_BYPASS_DPD BIT(25)
#define REG_TX_TONE_IDX 0x1b2c
#define REG_DPD_LUT0 0x1b44
#define BIT_GLOSS_DB GENMASK(14, 12)
#define REG_DPD_CTL0_S1 0x1b5c
#define REG_DPD_CTL1_S1 0x1b60
#define REG_DPD_AGC 0x1b67
#define REG_TABLE_SEL 0x1b98
#define BIT_I_GAIN GENMASK(19, 16)
#define BIT_GAIN_RST BIT(15)
#define BIT_Q_GAIN_SEL GENMASK(14, 12)
#define BIT_Q_GAIN GENMASK(11, 0)
#define REG_TX_GAIN_SET 0x1b9c
#define BIT_GAPK_RPT_IDX GENMASK(11, 8)
#define REG_DPD_CTL0 0x1bb4
#define REG_SINGLE_TONE_SW 0x1bb8
#define BIT_IRQ_TEST_MODE BIT(20)
#define REG_R_CONFIG 0x1bcc
#define BIT_INNER_LB BIT(21)
#define BIT_IQ_SWITCH GENMASK(5, 0)
#define BIT_2G_SWING 0x2d
#define BIT_5G_SWING 0x36
#define REG_RXSRAM_CTL 0x1bd4
#define BIT_RPT_EN BIT(21)
#define BIT_RPT_SEL GENMASK(20, 16)
#define BIT_DPD_CLK GENMASK(7, 4)
#define REG_DPD_CTL11 0x1be4
#define REG_DPD_CTL12 0x1be8
#define REG_DPD_CTL15 0x1bf4
#define REG_DPD_CTL16 0x1bf8
#define REG_STAT_RPT 0x1bfc
#define BIT_RPT_DGAIN GENMASK(27, 16)
#define BIT_GAPK_RPT0 GENMASK(3, 0)
#define BIT_GAPK_RPT1 GENMASK(7, 4)
#define BIT_GAPK_RPT2 GENMASK(11, 8)
#define BIT_GAPK_RPT3 GENMASK(15, 12)
#define BIT_GAPK_RPT4 GENMASK(19, 16)
#define BIT_GAPK_RPT5 GENMASK(23, 20)
#define BIT_GAPK_RPT6 GENMASK(27, 24)
#define BIT_GAPK_RPT7 GENMASK(31, 28)
#define REG_TXANT 0x1c28
#define REG_IQK_CTRL 0x1c38
#define REG_ENCCK 0x1c3c
#define BIT_CCK_BLK_EN BIT(1)
#define BIT_CCK_OFDM_BLK_EN (BIT(0) | BIT(1))
#define REG_CCAMSK 0x1c80
#define REG_RSTB 0x1c90
#define BIT_RSTB_3WIRE BIT(8)
#define REG_CH_DELAY_EXTR2 0x1cd0
#define BIT_TST_IQK2SET_SRC BIT(31)
#define BIT_EN_IOQ_IQK_DPK BIT(30)
#define BIT_IQK_DPK_RESET_SRC BIT(29)
#define BIT_IQK_DPK_CLOCK_SRC BIT(28)
#define REG_RX_BREAK 0x1d2c
#define BIT_COM_RX_GCK_EN BIT(31)
#define REG_RXFNCTL 0x1d30
#define REG_CCA_OFF 0x1d58
#define BIT_CCA_ON_BY_PW GENMASK(11, 3)
#define REG_RXIGI 0x1d70
#define REG_ENFN 0x1e24
#define BIT_IQK_DPK_EN BIT(17)
#define REG_TXANTSEG 0x1e28
#define BIT_ANTSEG GENMASK(3, 0)
#define REG_TXLGMAP 0x1e2c
#define REG_CCKPATH 0x1e5c
#define REG_TX_FIFO 0x1e70
#define BIT_STOP_TX GENMASK(3, 0)
#define REG_CNT_CTRL 0x1eb4
#define BIT_ALL_CNT_RST BIT(25)
#define REG_OFDM_FACNT 0x2d00
#define REG_OFDM_FACNT1 0x2d04
#define REG_OFDM_FACNT2 0x2d08
#define REG_OFDM_FACNT3 0x2d0c
#define REG_OFDM_FACNT4 0x2d10
#define REG_OFDM_FACNT5 0x2d20
#define REG_RPT_CIP 0x2d9c
#define BIT_RPT_CIP_STATUS GENMASK(7, 0)
#define REG_OFDM_TXCNT 0x2de0
#define REG_ORITXCODE2 0x4100
#define REG_3WIRE2 0x410c
#define REG_ANAPAR_B 0x4130
#define REG_RFTXEN_GCK_B 0x4164
#define REG_DIS_SHARE_RX_B 0x416c
#define BIT_EXT_TIA_BW BIT(1)
#define REG_RXAGCCTL 0x41ac
#define REG_DCKB_I_0 0x41bc
#define REG_DCKB_I_1 0x41c0
#define REG_DCKB_Q_0 0x41d8
#define REG_DCKB_Q_1 0x41dc
#define RF_MODE_TRXAGC 0x00
#define BIT_RF_MODE GENMASK(19, 16)
#define BIT_RXAGC GENMASK(9, 5)
#define BIT_TXAGC GENMASK(4, 0)
#define RF_RXAGC_OFFSET 0x19
#define RF_BW_TRXBB 0x1a
#define BIT_TX_CCK_IND BIT(16)
#define BIT_BW_TXBB GENMASK(14, 12)
#define BIT_BW_RXBB GENMASK(11, 10)
#define BIT_DBG_CCK_CCA BIT(1)
#define RF_TX_GAIN_OFFSET 0x55
#define BIT_BB_GAIN GENMASK(18, 14)
#define BIT_RF_GAIN GENMASK(4, 2)
#define RF_TX_GAIN 0x56
#define BIT_GAIN_TXBB GENMASK(4, 0)
#define RF_IDAC 0x58
#define BIT_TX_MODE GENMASK(19, 8)
#define RF_TX_RESULT 0x5f
#define BIT_GAIN_TX_PAD_H GENMASK(11, 8)
#define BIT_GAIN_TX_PAD_L GENMASK(7, 4)
#define RF_PA 0x60
#define RF_PABIAS_2G_MASK GENMASK(15, 12)
#define RF_PABIAS_5G_MASK GENMASK(19, 16)
#define RF_TXA_LB_SW 0x63
#define BIT_TXA_LB_ATT GENMASK(15, 14)
#define BIT_LB_SW GENMASK(13, 12)
#define BIT_LB_ATT GENMASK(4, 2)
#define RF_RXG_GAIN 0x87
#define BIT_RXG_GAIN BIT(18)
#define RF_RXA_MIX_GAIN 0x8a
#define BIT_RXA_MIX_GAIN GENMASK(4, 3)
#define RF_EXT_TIA_BW 0x8f
#define BIT_PW_EXT_TIA BIT(1)
#define RF_DIS_BYPASS_TXBB 0x9e
#define BIT_TXBB BIT(10)
#define BIT_TIA_BYPASS BIT(5)
#define RF_DEBUG 0xde
#define BIT_DE_PWR_TRIM BIT(19)
#define BIT_DE_TX_GAIN BIT(16)
#define BIT_DE_TRXBW BIT(2)
#define PPG_THERMAL_B 0x1b0
#define RF_THEMAL_MASK GENMASK(19, 16)
#define PPG_2GH_TXAB 0x1d2
#define PPG_2G_A_MASK GENMASK(3, 0)
#define PPG_2G_B_MASK GENMASK(7, 4)
#define PPG_2GL_TXAB 0x1d4
#define PPG_PABIAS_2GB 0x1d5
#define PPG_PABIAS_2GA 0x1d6
#define PPG_PABIAS_MASK GENMASK(3, 0)
#define PPG_PABIAS_5GB 0x1d7
#define PPG_PABIAS_5GA 0x1d8
#define PPG_5G_MASK GENMASK(4, 0)
#define PPG_5GH1_TXB 0x1db
#define PPG_5GH1_TXA 0x1dc
#define PPG_5GM2_TXB 0x1df
#define PPG_5GM2_TXA 0x1e0
#define PPG_5GM1_TXB 0x1e3
#define PPG_5GM1_TXA 0x1e4
#define PPG_5GL2_TXB 0x1e7
#define PPG_5GL2_TXA 0x1e8
#define PPG_5GL1_TXB 0x1eb
#define PPG_5GL1_TXA 0x1ec
#define PPG_2GM_TXAB 0x1ee
#define PPG_THERMAL_A 0x1ef
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8822C_TABLE_H__
#define __RTW8822C_TABLE_H__
extern const struct rtw_table rtw8822c_mac_tbl;
extern const struct rtw_table rtw8822c_agc_tbl;
extern const struct rtw_table rtw8822c_bb_tbl;
extern const struct rtw_table rtw8822c_bb_pg_type0_tbl;
extern const struct rtw_table rtw8822c_rf_a_tbl;
extern const struct rtw_table rtw8822c_rf_b_tbl;
extern const struct rtw_table rtw8822c_txpwr_lmt_type0_tbl;
extern const struct rtw_table rtw8822c_txpwr_lmt_type5_tbl;
extern const struct rtw_table rtw8822c_dpk_afe_no_dpk_tbl;
extern const struct rtw_table rtw8822c_dpk_afe_is_dpk_tbl;
extern const struct rtw_table rtw8822c_dpk_mac_bb_tbl;
extern const struct rtw_table rtw8822c_array_mp_cal_init_tbl;
#endif

View File

@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
#include "rtw8822ce.h"
static const struct pci_device_id rtw_8822ce_id_table[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC822),
.driver_data = (kernel_ulong_t)&rtw8822c_hw_spec
},
{
PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC82F),
.driver_data = (kernel_ulong_t)&rtw8822c_hw_spec
},
{}
};
MODULE_DEVICE_TABLE(pci, rtw_8822ce_id_table);
static struct pci_driver rtw_8822ce_driver = {
.name = "rtw_8822ce",
.id_table = rtw_8822ce_id_table,
.probe = rtw_pci_probe,
.remove = rtw_pci_remove,
.driver.pm = &rtw_pm_ops,
.shutdown = rtw_pci_shutdown,
#if defined(__FreeBSD__)
.bsddriver.name = KBUILD_MODNAME,
#endif
};
module_pci_driver(rtw_8822ce_driver);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822ce driver");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_8822CE_H_
#define __RTW_8822CE_H_
extern struct rtw_chip_info rtw8822c_hw_spec;
#endif

204
sys/contrib/dev/rtw88/rx.c Normal file
View File

@ -0,0 +1,204 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "rx.h"
#include "ps.h"
#include "debug.h"
#include "fw.h"
void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
struct rtw_vif *rtwvif;
hdr = (struct ieee80211_hdr *)skb->data;
if (!ieee80211_is_data(hdr->frame_control))
return;
if (!is_broadcast_ether_addr(hdr->addr1) &&
!is_multicast_ether_addr(hdr->addr1)) {
rtwdev->stats.rx_unicast += skb->len;
rtwdev->stats.rx_cnt++;
if (vif) {
rtwvif = (struct rtw_vif *)vif->drv_priv;
rtwvif->stats.rx_unicast += skb->len;
rtwvif->stats.rx_cnt++;
}
}
}
EXPORT_SYMBOL(rtw_rx_stats);
struct rtw_rx_addr_match_data {
struct rtw_dev *rtwdev;
struct ieee80211_hdr *hdr;
struct rtw_rx_pkt_stat *pkt_stat;
u8 *bssid;
};
static void rtw_rx_phy_stat(struct rtw_dev *rtwdev,
struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_hdr *hdr)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
struct rtw_pkt_count *cur_pkt_cnt = &dm_info->cur_pkt_count;
u8 rate_ss, rate_ss_evm, evm_id;
u8 i, idx;
dm_info->curr_rx_rate = pkt_stat->rate;
if (ieee80211_is_beacon(hdr->frame_control))
cur_pkt_cnt->num_bcn_pkt++;
switch (pkt_stat->rate) {
case DESC_RATE1M...DESC_RATE11M:
goto pkt_num;
case DESC_RATE6M...DESC_RATE54M:
rate_ss = 0;
rate_ss_evm = 1;
evm_id = RTW_EVM_OFDM;
break;
case DESC_RATEMCS0...DESC_RATEMCS7:
case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT1SS_MCS9:
rate_ss = 1;
rate_ss_evm = 1;
evm_id = RTW_EVM_1SS;
break;
case DESC_RATEMCS8...DESC_RATEMCS15:
case DESC_RATEVHT2SS_MCS0...DESC_RATEVHT2SS_MCS9:
rate_ss = 2;
rate_ss_evm = 2;
evm_id = RTW_EVM_2SS_A;
break;
default:
rtw_warn(rtwdev, "unknown pkt rate = %d\n", pkt_stat->rate);
return;
}
for (i = 0; i < rate_ss_evm; i++) {
idx = evm_id + i;
ewma_evm_add(&dm_info->ewma_evm[idx],
dm_info->rx_evm_dbm[i]);
}
for (i = 0; i < rtwdev->hal.rf_path_num; i++) {
idx = RTW_SNR_OFDM_A + 4 * rate_ss + i;
ewma_snr_add(&dm_info->ewma_snr[idx],
dm_info->rx_snr[i]);
}
pkt_num:
cur_pkt_cnt->num_qry_pkt[pkt_stat->rate]++;
}
static void rtw_rx_addr_match_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct rtw_rx_addr_match_data *iter_data = data;
struct ieee80211_sta *sta;
struct ieee80211_hdr *hdr = iter_data->hdr;
struct rtw_dev *rtwdev = iter_data->rtwdev;
struct rtw_sta_info *si;
struct rtw_rx_pkt_stat *pkt_stat = iter_data->pkt_stat;
u8 *bssid = iter_data->bssid;
if (!ether_addr_equal(vif->bss_conf.bssid, bssid))
return;
if (!(ether_addr_equal(vif->addr, hdr->addr1) ||
ieee80211_is_beacon(hdr->frame_control)))
return;
rtw_rx_phy_stat(rtwdev, pkt_stat, hdr);
sta = ieee80211_find_sta_by_ifaddr(rtwdev->hw, hdr->addr2,
vif->addr);
if (!sta)
return;
si = (struct rtw_sta_info *)sta->drv_priv;
ewma_rssi_add(&si->avg_rssi, pkt_stat->rssi);
}
static void rtw_rx_addr_match(struct rtw_dev *rtwdev,
struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_hdr *hdr)
{
struct rtw_rx_addr_match_data data = {};
if (pkt_stat->crc_err || pkt_stat->icv_err || !pkt_stat->phy_status ||
ieee80211_is_ctl(hdr->frame_control))
return;
data.rtwdev = rtwdev;
data.hdr = hdr;
data.pkt_stat = pkt_stat;
data.bssid = get_hdr_bssid(hdr);
rtw_iterate_vifs_atomic(rtwdev, rtw_rx_addr_match_iter, &data);
}
static void rtw_set_rx_freq_by_pktstat(struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_rx_status *rx_status)
{
rx_status->freq = pkt_stat->freq;
rx_status->band = pkt_stat->band;
}
void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rx_status,
u8 *phy_status)
{
struct ieee80211_hw *hw = rtwdev->hw;
u8 path;
memset(rx_status, 0, sizeof(*rx_status));
rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->band = hw->conf.chandef.chan->band;
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD))
rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status);
if (pkt_stat->crc_err)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (pkt_stat->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
if (pkt_stat->rate >= DESC_RATEVHT1SS_MCS0)
rx_status->encoding = RX_ENC_VHT;
else if (pkt_stat->rate >= DESC_RATEMCS0)
rx_status->encoding = RX_ENC_HT;
if (rx_status->band == NL80211_BAND_5GHZ &&
pkt_stat->rate >= DESC_RATE6M &&
pkt_stat->rate <= DESC_RATE54M) {
rx_status->rate_idx = pkt_stat->rate - DESC_RATE6M;
} else if (rx_status->band == NL80211_BAND_2GHZ &&
pkt_stat->rate >= DESC_RATE1M &&
pkt_stat->rate <= DESC_RATE54M) {
rx_status->rate_idx = pkt_stat->rate - DESC_RATE1M;
} else if (pkt_stat->rate >= DESC_RATEMCS0) {
rtw_desc_to_mcsrate(pkt_stat->rate, &rx_status->rate_idx,
&rx_status->nss);
}
rx_status->flag |= RX_FLAG_MACTIME_START;
rx_status->mactime = pkt_stat->tsf_low;
if (pkt_stat->bw == RTW_CHANNEL_WIDTH_80)
rx_status->bw = RATE_INFO_BW_80;
else if (pkt_stat->bw == RTW_CHANNEL_WIDTH_40)
rx_status->bw = RATE_INFO_BW_40;
else
rx_status->bw = RATE_INFO_BW_20;
rx_status->signal = pkt_stat->signal_power;
for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
rx_status->chains |= BIT(path);
rx_status->chain_signal[path] = pkt_stat->rx_power[path];
}
rtw_rx_addr_match(rtwdev, pkt_stat, hdr);
}
EXPORT_SYMBOL(rtw_rx_fill_rx_status);

View File

@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_RX_H_
#define __RTW_RX_H_
enum rtw_rx_desc_enc {
RX_DESC_ENC_NONE = 0,
RX_DESC_ENC_WEP40 = 1,
RX_DESC_ENC_TKIP_WO_MIC = 2,
RX_DESC_ENC_TKIP_MIC = 3,
RX_DESC_ENC_AES = 4,
RX_DESC_ENC_WEP104 = 5,
};
#define GET_RX_DESC_PHYST(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(26))
#define GET_RX_DESC_ICV_ERR(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(15))
#define GET_RX_DESC_CRC32(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(14))
#define GET_RX_DESC_SWDEC(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(27))
#define GET_RX_DESC_C2H(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x02), BIT(28))
#define GET_RX_DESC_PKT_LEN(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(13, 0))
#define GET_RX_DESC_DRV_INFO_SIZE(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(19, 16))
#define GET_RX_DESC_SHIFT(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(25, 24))
#define GET_RX_DESC_ENC_TYPE(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(22, 20))
#define GET_RX_DESC_RX_RATE(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x03), GENMASK(6, 0))
#define GET_RX_DESC_MACID(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x01), GENMASK(6, 0))
#define GET_RX_DESC_PPDU_CNT(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x02), GENMASK(30, 29))
#define GET_RX_DESC_TSFL(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0))
void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct sk_buff *skb);
void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rx_status,
u8 *phy_status);
#endif

114
sys/contrib/dev/rtw88/sar.c Normal file
View File

@ -0,0 +1,114 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2021 Realtek Corporation
*/
#include "sar.h"
#include "phy.h"
#include "debug.h"
s8 rtw_query_sar(struct rtw_dev *rtwdev, const struct rtw_sar_arg *arg)
{
const struct rtw_hal *hal = &rtwdev->hal;
const struct rtw_sar *sar = &hal->sar;
switch (sar->src) {
default:
rtw_warn(rtwdev, "unknown SAR source: %d\n", sar->src);
fallthrough;
case RTW_SAR_SOURCE_NONE:
return (s8)rtwdev->chip->max_power_index;
case RTW_SAR_SOURCE_COMMON:
return sar->cfg[arg->path][arg->rs].common[arg->sar_band];
}
}
static int rtw_apply_sar(struct rtw_dev *rtwdev, const struct rtw_sar *new)
{
struct rtw_hal *hal = &rtwdev->hal;
struct rtw_sar *sar = &hal->sar;
if (sar->src != RTW_SAR_SOURCE_NONE && new->src != sar->src) {
rtw_warn(rtwdev, "SAR source: %d is in use\n", sar->src);
return -EBUSY;
}
*sar = *new;
rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
return 0;
}
static s8 rtw_sar_to_phy(struct rtw_dev *rtwdev, u8 fct, s32 sar,
const struct rtw_sar_arg *arg)
{
struct rtw_hal *hal = &rtwdev->hal;
u8 txgi = rtwdev->chip->txgi_factor;
u8 max = rtwdev->chip->max_power_index;
s32 tmp;
s8 base;
tmp = fct > txgi ? sar >> (fct - txgi) : sar << (txgi - fct);
base = arg->sar_band == RTW_SAR_BAND_0 ?
hal->tx_pwr_by_rate_base_2g[arg->path][arg->rs] :
hal->tx_pwr_by_rate_base_5g[arg->path][arg->rs];
return (s8)clamp_t(s32, tmp, -max - 1, max) - base;
}
static const struct cfg80211_sar_freq_ranges rtw_common_sar_freq_ranges[] = {
[RTW_SAR_BAND_0] = { .start_freq = 2412, .end_freq = 2484, },
[RTW_SAR_BAND_1] = { .start_freq = 5180, .end_freq = 5320, },
[RTW_SAR_BAND_3] = { .start_freq = 5500, .end_freq = 5720, },
[RTW_SAR_BAND_4] = { .start_freq = 5745, .end_freq = 5825, },
};
rtw88_static_assert(ARRAY_SIZE(rtw_common_sar_freq_ranges) == RTW_SAR_BAND_NR);
const struct cfg80211_sar_capa rtw_sar_capa = {
.type = NL80211_SAR_TYPE_POWER,
.num_freq_ranges = RTW_SAR_BAND_NR,
.freq_ranges = rtw_common_sar_freq_ranges,
};
int rtw_set_sar_specs(struct rtw_dev *rtwdev,
const struct cfg80211_sar_specs *sar)
{
struct rtw_sar_arg arg = {0};
struct rtw_sar new = {0};
u32 idx, i, j, k;
s32 power;
s8 val;
if (sar->type != NL80211_SAR_TYPE_POWER)
return -EINVAL;
memset(&new, rtwdev->chip->max_power_index, sizeof(new));
new.src = RTW_SAR_SOURCE_COMMON;
for (i = 0; i < sar->num_sub_specs; i++) {
idx = sar->sub_specs[i].freq_range_index;
if (idx >= RTW_SAR_BAND_NR)
return -EINVAL;
power = sar->sub_specs[i].power;
rtw_info(rtwdev, "On freq %u to %u, set SAR %d in 1/%lu dBm\n",
rtw_common_sar_freq_ranges[idx].start_freq,
rtw_common_sar_freq_ranges[idx].end_freq,
power, BIT(RTW_COMMON_SAR_FCT));
for (j = 0; j < RTW_RF_PATH_MAX; j++) {
for (k = 0; k < RTW_RATE_SECTION_MAX; k++) {
arg = (struct rtw_sar_arg){
.sar_band = idx,
.path = j,
.rs = k,
};
val = rtw_sar_to_phy(rtwdev, RTW_COMMON_SAR_FCT,
power, &arg);
new.cfg[j][k].common[idx] = val;
}
}
}
return rtw_apply_sar(rtwdev, &new);
}

View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2021 Realtek Corporation
*/
#include "main.h"
/* NL80211_SAR_TYPE_POWER means unit is in 0.25 dBm,
* where 0.25 = 1/4 = 2^(-2), so make factor 2.
*/
#define RTW_COMMON_SAR_FCT 2
struct rtw_sar_arg {
u8 sar_band;
u8 path;
u8 rs;
};
extern const struct cfg80211_sar_capa rtw_sar_capa;
s8 rtw_query_sar(struct rtw_dev *rtwdev, const struct rtw_sar_arg *arg);
int rtw_set_sar_specs(struct rtw_dev *rtwdev,
const struct cfg80211_sar_specs *sar);

145
sys/contrib/dev/rtw88/sec.c Normal file
View File

@ -0,0 +1,145 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "sec.h"
#include "reg.h"
int rtw_sec_get_free_cam(struct rtw_sec_desc *sec)
{
/* if default key search is enabled, the first 4 cam entries
* are used to direct map to group key with its key->key_idx, so
* driver should use cam entries after 4 to install pairwise key
*/
if (sec->default_key_search)
return find_next_zero_bit(sec->cam_map, RTW_MAX_SEC_CAM_NUM,
RTW_SEC_DEFAULT_KEY_NUM);
return find_first_zero_bit(sec->cam_map, RTW_MAX_SEC_CAM_NUM);
}
void rtw_sec_write_cam(struct rtw_dev *rtwdev,
struct rtw_sec_desc *sec,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
u8 hw_key_type, u8 hw_key_idx)
{
struct rtw_cam_entry *cam = &sec->cam_table[hw_key_idx];
u32 write_cmd;
u32 command;
u32 content;
u32 addr;
int i, j;
set_bit(hw_key_idx, sec->cam_map);
cam->valid = true;
cam->group = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
cam->hw_key_type = hw_key_type;
cam->key = key;
if (sta)
ether_addr_copy(cam->addr, sta->addr);
else
eth_broadcast_addr(cam->addr);
write_cmd = RTW_SEC_CMD_WRITE_ENABLE | RTW_SEC_CMD_POLLING;
addr = hw_key_idx << RTW_SEC_CAM_ENTRY_SHIFT;
for (i = 7; i >= 0; i--) {
switch (i) {
case 0:
content = ((key->keyidx & 0x3)) |
((hw_key_type & 0x7) << 2) |
(cam->group << 6) |
(cam->valid << 15) |
(cam->addr[0] << 16) |
(cam->addr[1] << 24);
break;
case 1:
content = (cam->addr[2]) |
(cam->addr[3] << 8) |
(cam->addr[4] << 16) |
(cam->addr[5] << 24);
break;
case 6:
case 7:
content = 0;
break;
default:
j = (i - 2) << 2;
content = (key->key[j]) |
(key->key[j + 1] << 8) |
(key->key[j + 2] << 16) |
(key->key[j + 3] << 24);
break;
}
command = write_cmd | (addr + i);
rtw_write32(rtwdev, RTW_SEC_WRITE_REG, content);
rtw_write32(rtwdev, RTW_SEC_CMD_REG, command);
}
}
void rtw_sec_clear_cam(struct rtw_dev *rtwdev,
struct rtw_sec_desc *sec,
u8 hw_key_idx)
{
struct rtw_cam_entry *cam = &sec->cam_table[hw_key_idx];
u32 write_cmd;
u32 command;
u32 addr;
clear_bit(hw_key_idx, sec->cam_map);
cam->valid = false;
cam->key = NULL;
eth_zero_addr(cam->addr);
write_cmd = RTW_SEC_CMD_WRITE_ENABLE | RTW_SEC_CMD_POLLING;
addr = hw_key_idx << RTW_SEC_CAM_ENTRY_SHIFT;
command = write_cmd | addr;
rtw_write32(rtwdev, RTW_SEC_WRITE_REG, 0);
rtw_write32(rtwdev, RTW_SEC_CMD_REG, command);
}
u8 rtw_sec_cam_pg_backup(struct rtw_dev *rtwdev, u8 *used_cam)
{
struct rtw_sec_desc *sec = &rtwdev->sec;
u8 offset = 0;
u8 count, n;
if (!used_cam)
return 0;
for (count = 0; count < MAX_PG_CAM_BACKUP_NUM; count++) {
n = find_next_bit(sec->cam_map, RTW_MAX_SEC_CAM_NUM, offset);
if (n == RTW_MAX_SEC_CAM_NUM)
break;
used_cam[count] = n;
offset = n + 1;
}
return count;
}
void rtw_sec_enable_sec_engine(struct rtw_dev *rtwdev)
{
struct rtw_sec_desc *sec = &rtwdev->sec;
u16 ctrl_reg;
u16 sec_config;
/* default use default key search for now */
sec->default_key_search = true;
ctrl_reg = rtw_read16(rtwdev, REG_CR);
ctrl_reg |= RTW_SEC_ENGINE_EN;
rtw_write16(rtwdev, REG_CR, ctrl_reg);
sec_config = rtw_read16(rtwdev, RTW_SEC_CONFIG);
sec_config |= RTW_SEC_TX_DEC_EN | RTW_SEC_RX_DEC_EN;
if (sec->default_key_search)
sec_config |= RTW_SEC_TX_UNI_USE_DK | RTW_SEC_RX_UNI_USE_DK |
RTW_SEC_TX_BC_USE_DK | RTW_SEC_RX_BC_USE_DK;
rtw_write16(rtwdev, RTW_SEC_CONFIG, sec_config);
}

View File

@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_SEC_H_
#define __RTW_SEC_H_
#define RTW_SEC_CMD_REG 0x670
#define RTW_SEC_WRITE_REG 0x674
#define RTW_SEC_READ_REG 0x678
#define RTW_SEC_CONFIG 0x680
#define RTW_SEC_CAM_ENTRY_SHIFT 3
#define RTW_SEC_DEFAULT_KEY_NUM 4
#define RTW_SEC_CMD_WRITE_ENABLE BIT(16)
#define RTW_SEC_CMD_CLEAR BIT(30)
#define RTW_SEC_CMD_POLLING BIT(31)
#define RTW_SEC_TX_UNI_USE_DK BIT(0)
#define RTW_SEC_RX_UNI_USE_DK BIT(1)
#define RTW_SEC_TX_DEC_EN BIT(2)
#define RTW_SEC_RX_DEC_EN BIT(3)
#define RTW_SEC_TX_BC_USE_DK BIT(6)
#define RTW_SEC_RX_BC_USE_DK BIT(7)
#define RTW_SEC_ENGINE_EN BIT(9)
int rtw_sec_get_free_cam(struct rtw_sec_desc *sec);
void rtw_sec_write_cam(struct rtw_dev *rtwdev,
struct rtw_sec_desc *sec,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
u8 hw_key_type, u8 hw_key_idx);
void rtw_sec_clear_cam(struct rtw_dev *rtwdev,
struct rtw_sec_desc *sec,
u8 hw_key_idx);
u8 rtw_sec_cam_pg_backup(struct rtw_dev *rtwdev, u8 *used_cam);
void rtw_sec_enable_sec_engine(struct rtw_dev *rtwdev);
#endif

667
sys/contrib/dev/rtw88/tx.c Normal file
View File

@ -0,0 +1,667 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "tx.h"
#include "fw.h"
#include "ps.h"
#include "debug.h"
static
void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
struct rtw_vif *rtwvif;
hdr = (struct ieee80211_hdr *)skb->data;
if (!ieee80211_is_data(hdr->frame_control))
return;
if (!is_broadcast_ether_addr(hdr->addr1) &&
!is_multicast_ether_addr(hdr->addr1)) {
rtwdev->stats.tx_unicast += skb->len;
rtwdev->stats.tx_cnt++;
if (vif) {
rtwvif = (struct rtw_vif *)vif->drv_priv;
rtwvif->stats.tx_unicast += skb->len;
rtwvif->stats.tx_cnt++;
}
}
}
void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
{
__le32 *txdesc = (__le32 *)skb->data;
SET_TX_DESC_TXPKTSIZE(txdesc, pkt_info->tx_pkt_size);
SET_TX_DESC_OFFSET(txdesc, pkt_info->offset);
SET_TX_DESC_PKT_OFFSET(txdesc, pkt_info->pkt_offset);
SET_TX_DESC_QSEL(txdesc, pkt_info->qsel);
SET_TX_DESC_BMC(txdesc, pkt_info->bmc);
SET_TX_DESC_RATE_ID(txdesc, pkt_info->rate_id);
SET_TX_DESC_DATARATE(txdesc, pkt_info->rate);
SET_TX_DESC_DISDATAFB(txdesc, pkt_info->dis_rate_fallback);
SET_TX_DESC_USE_RATE(txdesc, pkt_info->use_rate);
SET_TX_DESC_SEC_TYPE(txdesc, pkt_info->sec_type);
SET_TX_DESC_DATA_BW(txdesc, pkt_info->bw);
SET_TX_DESC_SW_SEQ(txdesc, pkt_info->seq);
SET_TX_DESC_MAX_AGG_NUM(txdesc, pkt_info->ampdu_factor);
SET_TX_DESC_AMPDU_DENSITY(txdesc, pkt_info->ampdu_density);
SET_TX_DESC_DATA_STBC(txdesc, pkt_info->stbc);
SET_TX_DESC_DATA_LDPC(txdesc, pkt_info->ldpc);
SET_TX_DESC_AGG_EN(txdesc, pkt_info->ampdu_en);
SET_TX_DESC_LS(txdesc, pkt_info->ls);
SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi);
SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report);
SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn);
SET_TX_DESC_USE_RTS(txdesc, pkt_info->rts);
if (pkt_info->rts) {
SET_TX_DESC_RTSRATE(txdesc, DESC_RATE24M);
SET_TX_DESC_DATA_RTS_SHORT(txdesc, 1);
}
SET_TX_DESC_DISQSELSEQ(txdesc, pkt_info->dis_qselseq);
SET_TX_DESC_EN_HWSEQ(txdesc, pkt_info->en_hwseq);
SET_TX_DESC_HW_SSN_SEL(txdesc, pkt_info->hw_ssn_sel);
SET_TX_DESC_NAVUSEHDR(txdesc, pkt_info->nav_use_hdr);
SET_TX_DESC_BT_NULL(txdesc, pkt_info->bt_null);
}
EXPORT_SYMBOL(rtw_tx_fill_tx_desc);
static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta)
{
u8 exp = sta->ht_cap.ampdu_factor;
/* the least ampdu factor is 8K, and the value in the tx desc is the
* max aggregation num, which represents val * 2 packets can be
* aggregated in an AMPDU, so here we should use 8/2=4 as the base
*/
return (BIT(2) << exp) - 1;
}
static u8 get_tx_ampdu_density(struct ieee80211_sta *sta)
{
return sta->ht_cap.ampdu_density;
}
static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev,
struct ieee80211_sta *sta)
{
u8 rate;
if (rtwdev->hal.rf_type == RF_2T2R && sta->ht_cap.mcs.rx_mask[1] != 0)
rate = DESC_RATEMCS15;
else
rate = DESC_RATEMCS7;
return rate;
}
static u8 get_highest_vht_tx_rate(struct rtw_dev *rtwdev,
struct ieee80211_sta *sta)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
u8 rate;
u16 tx_mcs_map;
tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map);
if (efuse->hw_cap.nss == 1) {
switch (tx_mcs_map & 0x3) {
case IEEE80211_VHT_MCS_SUPPORT_0_7:
rate = DESC_RATEVHT1SS_MCS7;
break;
case IEEE80211_VHT_MCS_SUPPORT_0_8:
rate = DESC_RATEVHT1SS_MCS8;
break;
default:
case IEEE80211_VHT_MCS_SUPPORT_0_9:
rate = DESC_RATEVHT1SS_MCS9;
break;
}
} else if (efuse->hw_cap.nss >= 2) {
switch ((tx_mcs_map & 0xc) >> 2) {
case IEEE80211_VHT_MCS_SUPPORT_0_7:
rate = DESC_RATEVHT2SS_MCS7;
break;
case IEEE80211_VHT_MCS_SUPPORT_0_8:
rate = DESC_RATEVHT2SS_MCS8;
break;
default:
case IEEE80211_VHT_MCS_SUPPORT_0_9:
rate = DESC_RATEVHT2SS_MCS9;
break;
}
} else {
rate = DESC_RATEVHT1SS_MCS9;
}
return rate;
}
static void rtw_tx_report_enable(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info)
{
struct rtw_tx_report *tx_report = &rtwdev->tx_report;
/* [11:8], reserved, fills with zero
* [7:2], tx report sequence number
* [1:0], firmware use, fills with zero
*/
pkt_info->sn = (atomic_inc_return(&tx_report->sn) << 2) & 0xfc;
pkt_info->report = true;
}
void rtw_tx_report_purge_timer(struct timer_list *t)
{
struct rtw_dev *rtwdev = from_timer(rtwdev, t, tx_report.purge_timer);
struct rtw_tx_report *tx_report = &rtwdev->tx_report;
unsigned long flags;
if (skb_queue_len(&tx_report->queue) == 0)
return;
rtw_warn(rtwdev, "failed to get tx report from firmware\n");
spin_lock_irqsave(&tx_report->q_lock, flags);
skb_queue_purge(&tx_report->queue);
spin_unlock_irqrestore(&tx_report->q_lock, flags);
}
void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn)
{
struct rtw_tx_report *tx_report = &rtwdev->tx_report;
unsigned long flags;
u8 *drv_data;
/* pass sn to tx report handler through driver data */
drv_data = (u8 *)IEEE80211_SKB_CB(skb)->status.status_driver_data;
*drv_data = sn;
spin_lock_irqsave(&tx_report->q_lock, flags);
__skb_queue_tail(&tx_report->queue, skb);
spin_unlock_irqrestore(&tx_report->q_lock, flags);
mod_timer(&tx_report->purge_timer, jiffies + RTW_TX_PROBE_TIMEOUT);
}
EXPORT_SYMBOL(rtw_tx_report_enqueue);
static void rtw_tx_report_tx_status(struct rtw_dev *rtwdev,
struct sk_buff *skb, bool acked)
{
struct ieee80211_tx_info *info;
info = IEEE80211_SKB_CB(skb);
ieee80211_tx_info_clear_status(info);
if (acked)
info->flags |= IEEE80211_TX_STAT_ACK;
else
info->flags &= ~IEEE80211_TX_STAT_ACK;
ieee80211_tx_status_irqsafe(rtwdev->hw, skb);
}
void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src)
{
struct rtw_tx_report *tx_report = &rtwdev->tx_report;
struct rtw_c2h_cmd *c2h;
struct sk_buff *cur, *tmp;
unsigned long flags;
u8 sn, st;
u8 *n;
c2h = get_c2h_from_skb(skb);
if (src == C2H_CCX_TX_RPT) {
sn = GET_CCX_REPORT_SEQNUM_V0(c2h->payload);
st = GET_CCX_REPORT_STATUS_V0(c2h->payload);
} else {
sn = GET_CCX_REPORT_SEQNUM_V1(c2h->payload);
st = GET_CCX_REPORT_STATUS_V1(c2h->payload);
}
spin_lock_irqsave(&tx_report->q_lock, flags);
skb_queue_walk_safe(&tx_report->queue, cur, tmp) {
n = (u8 *)IEEE80211_SKB_CB(cur)->status.status_driver_data;
if (*n == sn) {
__skb_unlink(cur, &tx_report->queue);
rtw_tx_report_tx_status(rtwdev, cur, st == 0);
break;
}
}
spin_unlock_irqrestore(&tx_report->q_lock, flags);
}
static u8 rtw_get_mgmt_rate(struct rtw_dev *rtwdev, struct sk_buff *skb,
u8 lowest_rate, bool ignore_rate)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = tx_info->control.vif;
bool force_lowest = test_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags);
if (!vif || !vif->bss_conf.basic_rates || ignore_rate || force_lowest)
return lowest_rate;
return __ffs(vif->bss_conf.basic_rates) + lowest_rate;
}
static void rtw_tx_pkt_info_update_rate(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct sk_buff *skb,
bool ignore_rate)
{
if (rtwdev->hal.current_band_type == RTW_BAND_2G) {
pkt_info->rate_id = RTW_RATEID_B_20M;
pkt_info->rate = rtw_get_mgmt_rate(rtwdev, skb, DESC_RATE1M,
ignore_rate);
} else {
pkt_info->rate_id = RTW_RATEID_G;
pkt_info->rate = rtw_get_mgmt_rate(rtwdev, skb, DESC_RATE6M,
ignore_rate);
}
pkt_info->use_rate = true;
pkt_info->dis_rate_fallback = true;
}
static void rtw_tx_pkt_info_update_sec(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 sec_type = 0;
if (info && 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:
sec_type = 0x01;
break;
case WLAN_CIPHER_SUITE_CCMP:
sec_type = 0x03;
break;
default:
break;
}
}
pkt_info->sec_type = sec_type;
}
static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct ieee80211_sta *sta,
struct sk_buff *skb)
{
rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb, false);
pkt_info->dis_qselseq = true;
pkt_info->en_hwseq = true;
pkt_info->hw_ssn_sel = 0;
/* TODO: need to change hw port and hw ssn sel for multiple vifs */
}
static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct ieee80211_sta *sta,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hw *hw = rtwdev->hw;
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
struct rtw_sta_info *si;
u8 fix_rate;
u16 seq;
u8 ampdu_factor = 0;
u8 ampdu_density = 0;
bool ampdu_en = false;
u8 rate = DESC_RATE6M;
u8 rate_id = 6;
u8 bw = RTW_CHANNEL_WIDTH_20;
bool stbc = false;
bool ldpc = false;
seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
/* for broadcast/multicast, use default values */
if (!sta)
goto out;
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
ampdu_en = true;
ampdu_factor = get_tx_ampdu_factor(sta);
ampdu_density = get_tx_ampdu_density(sta);
}
if (info->control.use_rts || skb->len > hw->wiphy->rts_threshold)
pkt_info->rts = true;
if (sta->vht_cap.vht_supported)
rate = get_highest_vht_tx_rate(rtwdev, sta);
else if (sta->ht_cap.ht_supported)
rate = get_highest_ht_tx_rate(rtwdev, sta);
else if (sta->supp_rates[0] <= 0xf)
rate = DESC_RATE11M;
else
rate = DESC_RATE54M;
si = (struct rtw_sta_info *)sta->drv_priv;
bw = si->bw_mode;
rate_id = si->rate_id;
stbc = si->stbc_en;
ldpc = si->ldpc_en;
out:
pkt_info->seq = seq;
pkt_info->ampdu_factor = ampdu_factor;
pkt_info->ampdu_density = ampdu_density;
pkt_info->ampdu_en = ampdu_en;
pkt_info->rate = rate;
pkt_info->rate_id = rate_id;
pkt_info->bw = bw;
pkt_info->stbc = stbc;
pkt_info->ldpc = ldpc;
fix_rate = dm_info->fix_rate;
if (fix_rate < DESC_RATE_MAX) {
pkt_info->rate = fix_rate;
pkt_info->dis_rate_fallback = true;
pkt_info->use_rate = true;
}
}
void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct ieee80211_sta *sta,
struct sk_buff *skb)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct rtw_sta_info *si;
struct ieee80211_vif *vif = NULL;
__le16 fc = hdr->frame_control;
bool bmc;
if (sta) {
si = (struct rtw_sta_info *)sta->drv_priv;
vif = si->vif;
}
if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc))
rtw_tx_mgmt_pkt_info_update(rtwdev, pkt_info, sta, skb);
else if (ieee80211_is_data(fc))
rtw_tx_data_pkt_info_update(rtwdev, pkt_info, sta, skb);
bmc = is_broadcast_ether_addr(hdr->addr1) ||
is_multicast_ether_addr(hdr->addr1);
if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
rtw_tx_report_enable(rtwdev, pkt_info);
pkt_info->bmc = bmc;
rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
pkt_info->tx_pkt_size = skb->len;
pkt_info->offset = chip->tx_pkt_desc_sz;
pkt_info->qsel = skb->priority;
pkt_info->ls = true;
/* maybe merge with tx status ? */
rtw_tx_stats(rtwdev, vif, skb);
}
void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct sk_buff *skb,
enum rtw_rsvd_packet_type type)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
bool bmc;
/* A beacon or dummy reserved page packet indicates that it is the first
* reserved page, and the qsel of it will be set in each hci.
*/
if (type != RSVD_BEACON && type != RSVD_DUMMY)
pkt_info->qsel = TX_DESC_QSEL_MGMT;
rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb, true);
bmc = is_broadcast_ether_addr(hdr->addr1) ||
is_multicast_ether_addr(hdr->addr1);
pkt_info->bmc = bmc;
pkt_info->tx_pkt_size = skb->len;
pkt_info->offset = chip->tx_pkt_desc_sz;
pkt_info->ls = true;
if (type == RSVD_PS_POLL) {
pkt_info->nav_use_hdr = true;
} else {
pkt_info->dis_qselseq = true;
pkt_info->en_hwseq = true;
pkt_info->hw_ssn_sel = 0;
}
if (type == RSVD_QOS_NULL)
pkt_info->bt_null = true;
rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
/* TODO: need to change hw port and hw ssn sel for multiple vifs */
}
struct sk_buff *
rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *buf, u32 size)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct sk_buff *skb;
u32 tx_pkt_desc_sz;
u32 length;
tx_pkt_desc_sz = chip->tx_pkt_desc_sz;
length = size + tx_pkt_desc_sz;
skb = dev_alloc_skb(length);
if (!skb) {
rtw_err(rtwdev, "failed to alloc write data rsvd page skb\n");
return NULL;
}
skb_reserve(skb, tx_pkt_desc_sz);
skb_put_data(skb, buf, size);
rtw_tx_rsvd_page_pkt_info_update(rtwdev, pkt_info, skb, RSVD_BEACON);
return skb;
}
EXPORT_SYMBOL(rtw_tx_write_data_rsvd_page_get);
struct sk_buff *
rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *buf, u32 size)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct sk_buff *skb;
u32 tx_pkt_desc_sz;
u32 length;
tx_pkt_desc_sz = chip->tx_pkt_desc_sz;
length = size + tx_pkt_desc_sz;
skb = dev_alloc_skb(length);
if (!skb) {
rtw_err(rtwdev, "failed to alloc write data h2c skb\n");
return NULL;
}
skb_reserve(skb, tx_pkt_desc_sz);
skb_put_data(skb, buf, size);
pkt_info->tx_pkt_size = size;
return skb;
}
EXPORT_SYMBOL(rtw_tx_write_data_h2c_get);
void rtw_tx(struct rtw_dev *rtwdev,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
struct rtw_tx_pkt_info pkt_info = {0};
int ret;
rtw_tx_pkt_info_update(rtwdev, &pkt_info, control->sta, skb);
ret = rtw_hci_tx_write(rtwdev, &pkt_info, skb);
if (ret) {
rtw_err(rtwdev, "failed to write TX skb to HCI\n");
goto out;
}
rtw_hci_tx_kick_off(rtwdev);
return;
out:
ieee80211_free_txskb(rtwdev->hw, skb);
}
static void rtw_txq_check_agg(struct rtw_dev *rtwdev,
struct rtw_txq *rtwtxq,
struct sk_buff *skb)
{
struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
struct ieee80211_tx_info *info;
struct rtw_sta_info *si;
if (test_bit(RTW_TXQ_AMPDU, &rtwtxq->flags)) {
info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_CTL_AMPDU;
return;
}
if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
return;
if (test_bit(RTW_TXQ_BLOCK_BA, &rtwtxq->flags))
return;
if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
return;
if (!txq->sta)
return;
si = (struct rtw_sta_info *)txq->sta->drv_priv;
set_bit(txq->tid, si->tid_ba);
ieee80211_queue_work(rtwdev->hw, &rtwdev->ba_work);
}
static int rtw_txq_push_skb(struct rtw_dev *rtwdev,
struct rtw_txq *rtwtxq,
struct sk_buff *skb)
{
struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
struct rtw_tx_pkt_info pkt_info = {0};
int ret;
rtw_txq_check_agg(rtwdev, rtwtxq, skb);
rtw_tx_pkt_info_update(rtwdev, &pkt_info, txq->sta, skb);
ret = rtw_hci_tx_write(rtwdev, &pkt_info, skb);
if (ret) {
rtw_err(rtwdev, "failed to write TX skb to HCI\n");
return ret;
}
rtwtxq->last_push = jiffies;
return 0;
}
static struct sk_buff *rtw_txq_dequeue(struct rtw_dev *rtwdev,
struct rtw_txq *rtwtxq)
{
struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
struct sk_buff *skb;
skb = ieee80211_tx_dequeue(rtwdev->hw, txq);
if (!skb)
return NULL;
return skb;
}
static void rtw_txq_push(struct rtw_dev *rtwdev,
struct rtw_txq *rtwtxq,
unsigned long frames)
{
struct sk_buff *skb;
int ret;
int i;
rcu_read_lock();
for (i = 0; i < frames; i++) {
skb = rtw_txq_dequeue(rtwdev, rtwtxq);
if (!skb)
break;
ret = rtw_txq_push_skb(rtwdev, rtwtxq, skb);
if (ret) {
rtw_err(rtwdev, "failed to pusk skb, ret %d\n", ret);
break;
}
}
rcu_read_unlock();
}
void rtw_tx_work(struct work_struct *w)
{
struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work);
struct rtw_txq *rtwtxq, *tmp;
spin_lock_bh(&rtwdev->txq_lock);
list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->txqs, list) {
struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
unsigned long frame_cnt;
unsigned long byte_cnt;
ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt);
rtw_txq_push(rtwdev, rtwtxq, frame_cnt);
list_del_init(&rtwtxq->list);
}
rtw_hci_tx_kick_off(rtwdev);
spin_unlock_bh(&rtwdev->txq_lock);
}
void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
{
struct rtw_txq *rtwtxq;
if (!txq)
return;
rtwtxq = (struct rtw_txq *)txq->drv_priv;
INIT_LIST_HEAD(&rtwtxq->list);
}
void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
{
struct rtw_txq *rtwtxq;
if (!txq)
return;
rtwtxq = (struct rtw_txq *)txq->drv_priv;
spin_lock_bh(&rtwdev->txq_lock);
if (!list_empty(&rtwtxq->list))
list_del_init(&rtwtxq->list);
spin_unlock_bh(&rtwdev->txq_lock);
}

122
sys/contrib/dev/rtw88/tx.h Normal file
View File

@ -0,0 +1,122 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_TX_H_
#define __RTW_TX_H_
#define RTK_TX_MAX_AGG_NUM_MASK 0x1f
#define RTW_TX_PROBE_TIMEOUT msecs_to_jiffies(500)
#define SET_TX_DESC_TXPKTSIZE(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(15, 0))
#define SET_TX_DESC_OFFSET(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(23, 16))
#define SET_TX_DESC_PKT_OFFSET(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(28, 24))
#define SET_TX_DESC_QSEL(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(12, 8))
#define SET_TX_DESC_BMC(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(24))
#define SET_TX_DESC_RATE_ID(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(20, 16))
#define SET_TX_DESC_DATARATE(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(6, 0))
#define SET_TX_DESC_DISDATAFB(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(10))
#define SET_TX_DESC_USE_RATE(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(8))
#define SET_TX_DESC_SEC_TYPE(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(23, 22))
#define SET_TX_DESC_DATA_BW(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(6, 5))
#define SET_TX_DESC_SW_SEQ(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(23, 12))
#define SET_TX_DESC_MAX_AGG_NUM(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(21, 17))
#define SET_TX_DESC_USE_RTS(tx_desc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(12))
#define SET_TX_DESC_RTSRATE(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(28, 24))
#define SET_TX_DESC_DATA_RTS_SHORT(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(12))
#define SET_TX_DESC_AMPDU_DENSITY(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, GENMASK(22, 20))
#define SET_TX_DESC_DATA_STBC(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(9, 8))
#define SET_TX_DESC_DATA_LDPC(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(7))
#define SET_TX_DESC_AGG_EN(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(12))
#define SET_TX_DESC_LS(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(26))
#define SET_TX_DESC_DATA_SHORT(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(4))
#define SET_TX_DESC_SPE_RPT(tx_desc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(19))
#define SET_TX_DESC_SW_DEFINE(tx_desc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x06, value, GENMASK(11, 0))
#define SET_TX_DESC_DISQSELSEQ(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(31))
#define SET_TX_DESC_EN_HWSEQ(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x08, value, BIT(15))
#define SET_TX_DESC_HW_SSN_SEL(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(7, 6))
#define SET_TX_DESC_NAVUSEHDR(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15))
#define SET_TX_DESC_BT_NULL(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23))
enum rtw_tx_desc_queue_select {
TX_DESC_QSEL_TID0 = 0,
TX_DESC_QSEL_TID1 = 1,
TX_DESC_QSEL_TID2 = 2,
TX_DESC_QSEL_TID3 = 3,
TX_DESC_QSEL_TID4 = 4,
TX_DESC_QSEL_TID5 = 5,
TX_DESC_QSEL_TID6 = 6,
TX_DESC_QSEL_TID7 = 7,
TX_DESC_QSEL_TID8 = 8,
TX_DESC_QSEL_TID9 = 9,
TX_DESC_QSEL_TID10 = 10,
TX_DESC_QSEL_TID11 = 11,
TX_DESC_QSEL_TID12 = 12,
TX_DESC_QSEL_TID13 = 13,
TX_DESC_QSEL_TID14 = 14,
TX_DESC_QSEL_TID15 = 15,
TX_DESC_QSEL_BEACON = 16,
TX_DESC_QSEL_HIGH = 17,
TX_DESC_QSEL_MGMT = 18,
TX_DESC_QSEL_H2C = 19,
};
enum rtw_rsvd_packet_type;
void rtw_tx(struct rtw_dev *rtwdev,
struct ieee80211_tx_control *control,
struct sk_buff *skb);
void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
void rtw_tx_work(struct work_struct *w);
void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct ieee80211_sta *sta,
struct sk_buff *skb);
void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb);
void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn);
void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src);
void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct sk_buff *skb,
enum rtw_rsvd_packet_type type);
struct sk_buff *
rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *buf, u32 size);
struct sk_buff *
rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *buf, u32 size);
#endif

View File

@ -0,0 +1,107 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "util.h"
#include "reg.h"
bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target)
{
u32 cnt;
for (cnt = 0; cnt < 1000; cnt++) {
if (rtw_read32_mask(rtwdev, addr, mask) == target)
return true;
udelay(10);
}
return false;
}
EXPORT_SYMBOL(check_hw_ready);
bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val)
{
struct rtw_chip_info *chip = rtwdev->chip;
const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr;
if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1))
return false;
rtw_write32(rtwdev, ltecoex->ctrl, 0x800F0000 | offset);
*val = rtw_read32(rtwdev, ltecoex->rdata);
return true;
}
bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value)
{
struct rtw_chip_info *chip = rtwdev->chip;
const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr;
if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1))
return false;
rtw_write32(rtwdev, ltecoex->wdata, value);
rtw_write32(rtwdev, ltecoex->ctrl, 0xC00F0000 | offset);
return true;
}
void rtw_restore_reg(struct rtw_dev *rtwdev,
struct rtw_backup_info *bckp, u32 num)
{
u8 len;
u32 reg;
u32 val;
int i;
for (i = 0; i < num; i++, bckp++) {
len = bckp->len;
reg = bckp->reg;
val = bckp->val;
switch (len) {
case 1:
rtw_write8(rtwdev, reg, (u8)val);
break;
case 2:
rtw_write16(rtwdev, reg, (u16)val);
break;
case 4:
rtw_write32(rtwdev, reg, (u32)val);
break;
default:
break;
}
}
}
EXPORT_SYMBOL(rtw_restore_reg);
void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss)
{
if (rate <= DESC_RATE54M)
return;
if (rate >= DESC_RATEVHT1SS_MCS0 &&
rate <= DESC_RATEVHT1SS_MCS9) {
*nss = 1;
*mcs = rate - DESC_RATEVHT1SS_MCS0;
} else if (rate >= DESC_RATEVHT2SS_MCS0 &&
rate <= DESC_RATEVHT2SS_MCS9) {
*nss = 2;
*mcs = rate - DESC_RATEVHT2SS_MCS0;
} else if (rate >= DESC_RATEVHT3SS_MCS0 &&
rate <= DESC_RATEVHT3SS_MCS9) {
*nss = 3;
*mcs = rate - DESC_RATEVHT3SS_MCS0;
} else if (rate >= DESC_RATEVHT4SS_MCS0 &&
rate <= DESC_RATEVHT4SS_MCS9) {
*nss = 4;
*mcs = rate - DESC_RATEVHT4SS_MCS0;
} else if (rate >= DESC_RATEMCS0 &&
rate <= DESC_RATEMCS15) {
*mcs = rate - DESC_RATEMCS0;
}
}

View File

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_UTIL_H__
#define __RTW_UTIL_H__
struct rtw_dev;
#define rtw_iterate_vifs(rtwdev, iterator, data) \
ieee80211_iterate_active_interfaces(rtwdev->hw, \
IEEE80211_IFACE_ITER_NORMAL, iterator, data)
#define rtw_iterate_vifs_atomic(rtwdev, iterator, data) \
ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, \
IEEE80211_IFACE_ITER_NORMAL, iterator, data)
#define rtw_iterate_stas_atomic(rtwdev, iterator, data) \
ieee80211_iterate_stations_atomic(rtwdev->hw, iterator, data)
#define rtw_iterate_keys(rtwdev, vif, iterator, data) \
ieee80211_iter_keys(rtwdev->hw, vif, iterator, data)
#define rtw_iterate_keys_rcu(rtwdev, vif, iterator, data) \
ieee80211_iter_keys_rcu((rtwdev)->hw, vif, iterator, data)
static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)
{
__le16 fc = hdr->frame_control;
u8 *bssid;
if (ieee80211_has_tods(fc))
bssid = hdr->addr1;
else if (ieee80211_has_fromds(fc))
bssid = hdr->addr2;
else
bssid = hdr->addr3;
return bssid;
}
#endif

913
sys/contrib/dev/rtw88/wow.c Normal file
View File

@ -0,0 +1,913 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "fw.h"
#include "wow.h"
#include "reg.h"
#include "debug.h"
#include "mac.h"
#include "ps.h"
static void rtw_wow_show_wakeup_reason(struct rtw_dev *rtwdev)
{
struct cfg80211_wowlan_nd_info nd_info;
struct cfg80211_wowlan_wakeup wakeup = {
.pattern_idx = -1,
};
u8 reason;
reason = rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON);
switch (reason) {
case RTW_WOW_RSN_RX_DEAUTH:
wakeup.disconnect = true;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx deauth\n");
break;
case RTW_WOW_RSN_DISCONNECT:
wakeup.disconnect = true;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: AP is off\n");
break;
case RTW_WOW_RSN_RX_MAGIC_PKT:
wakeup.magic_pkt = true;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx magic packet\n");
break;
case RTW_WOW_RSN_RX_GTK_REKEY:
wakeup.gtk_rekey_failure = true;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx gtk rekey\n");
break;
case RTW_WOW_RSN_RX_PATTERN_MATCH:
/* Current firmware and driver don't report pattern index
* Use pattern_idx to 0 defaultly.
*/
wakeup.pattern_idx = 0;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx pattern match packet\n");
break;
case RTW_WOW_RSN_RX_NLO:
/* Current firmware and driver don't report ssid index.
* Use 0 for n_matches based on its comment.
*/
nd_info.n_matches = 0;
wakeup.net_detect = &nd_info;
rtw_dbg(rtwdev, RTW_DBG_WOW, "Rx NLO\n");
break;
default:
rtw_warn(rtwdev, "Unknown wakeup reason %x\n", reason);
ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL,
GFP_KERNEL);
return;
}
ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup,
GFP_KERNEL);
}
static void rtw_wow_pattern_write_cam(struct rtw_dev *rtwdev, u8 addr,
u32 wdata)
{
rtw_write32(rtwdev, REG_WKFMCAM_RWD, wdata);
rtw_write32(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 |
BIT_WKFCAM_WE | BIT_WKFCAM_ADDR_V2(addr));
if (!check_hw_ready(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1, 0))
rtw_err(rtwdev, "failed to write pattern cam\n");
}
static void rtw_wow_pattern_write_cam_ent(struct rtw_dev *rtwdev, u8 id,
struct rtw_wow_pattern *rtw_pattern)
{
int i;
u8 addr;
u32 wdata;
for (i = 0; i < RTW_MAX_PATTERN_MASK_SIZE / 4; i++) {
addr = (id << 3) + i;
wdata = rtw_pattern->mask[i * 4];
wdata |= rtw_pattern->mask[i * 4 + 1] << 8;
wdata |= rtw_pattern->mask[i * 4 + 2] << 16;
wdata |= rtw_pattern->mask[i * 4 + 3] << 24;
rtw_wow_pattern_write_cam(rtwdev, addr, wdata);
}
wdata = rtw_pattern->crc;
addr = (id << 3) + RTW_MAX_PATTERN_MASK_SIZE / 4;
switch (rtw_pattern->type) {
case RTW_PATTERN_BROADCAST:
wdata |= BIT_WKFMCAM_BC | BIT_WKFMCAM_VALID;
break;
case RTW_PATTERN_MULTICAST:
wdata |= BIT_WKFMCAM_MC | BIT_WKFMCAM_VALID;
break;
case RTW_PATTERN_UNICAST:
wdata |= BIT_WKFMCAM_UC | BIT_WKFMCAM_VALID;
break;
default:
break;
}
rtw_wow_pattern_write_cam(rtwdev, addr, wdata);
}
/* RTK internal CRC16 for Pattern Cam */
static u16 __rtw_cal_crc16(u8 data, u16 crc)
{
u8 shift_in, data_bit;
u8 crc_bit4, crc_bit11, crc_bit15;
u16 crc_result;
int index;
for (index = 0; index < 8; index++) {
crc_bit15 = ((crc & BIT(15)) ? 1 : 0);
data_bit = (data & (BIT(0) << index) ? 1 : 0);
shift_in = crc_bit15 ^ data_bit;
crc_result = crc << 1;
if (shift_in == 0)
crc_result &= (~BIT(0));
else
crc_result |= BIT(0);
crc_bit11 = ((crc & BIT(11)) ? 1 : 0) ^ shift_in;
if (crc_bit11 == 0)
crc_result &= (~BIT(12));
else
crc_result |= BIT(12);
crc_bit4 = ((crc & BIT(4)) ? 1 : 0) ^ shift_in;
if (crc_bit4 == 0)
crc_result &= (~BIT(5));
else
crc_result |= BIT(5);
crc = crc_result;
}
return crc;
}
static u16 rtw_calc_crc(u8 *pdata, int length)
{
u16 crc = 0xffff;
int i;
for (i = 0; i < length; i++)
crc = __rtw_cal_crc16(pdata[i], crc);
/* get 1' complement */
return ~crc;
}
static void rtw_wow_pattern_generate(struct rtw_dev *rtwdev,
struct rtw_vif *rtwvif,
const struct cfg80211_pkt_pattern *pkt_pattern,
struct rtw_wow_pattern *rtw_pattern)
{
const u8 *mask;
const u8 *pattern;
u8 mask_hw[RTW_MAX_PATTERN_MASK_SIZE] = {0};
u8 content[RTW_MAX_PATTERN_SIZE] = {0};
u8 mac_addr[ETH_ALEN] = {0};
u8 mask_len;
u16 count;
int len;
int i;
pattern = pkt_pattern->pattern;
len = pkt_pattern->pattern_len;
mask = pkt_pattern->mask;
ether_addr_copy(mac_addr, rtwvif->mac_addr);
memset(rtw_pattern, 0, sizeof(*rtw_pattern));
mask_len = DIV_ROUND_UP(len, 8);
if (is_broadcast_ether_addr(pattern))
rtw_pattern->type = RTW_PATTERN_BROADCAST;
else if (is_multicast_ether_addr(pattern))
rtw_pattern->type = RTW_PATTERN_MULTICAST;
else if (ether_addr_equal(pattern, mac_addr))
rtw_pattern->type = RTW_PATTERN_UNICAST;
else
rtw_pattern->type = RTW_PATTERN_INVALID;
/* translate mask from os to mask for hw
* pattern from OS uses 'ethenet frame', like this:
* | 6 | 6 | 2 | 20 | Variable | 4 |
* |--------+--------+------+-----------+------------+-----|
* | 802.3 Mac Header | IP Header | TCP Packet | FCS |
* | DA | SA | Type |
*
* BUT, packet catched by our HW is in '802.11 frame', begin from LLC
* | 24 or 30 | 6 | 2 | 20 | Variable | 4 |
* |-------------------+--------+------+-----------+------------+-----|
* | 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS |
* | Others | Tpye |
*
* Therefore, we need translate mask_from_OS to mask_to_hw.
* We should left-shift mask by 6 bits, then set the new bit[0~5] = 0,
* because new mask[0~5] means 'SA', but our HW packet begins from LLC,
* bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match.
*/
/* Shift 6 bits */
for (i = 0; i < mask_len - 1; i++) {
mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6));
mask_hw[i] |= u8_get_bits(mask[i + 1], GENMASK(5, 0)) << 2;
}
mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6));
/* Set bit 0-5 to zero */
mask_hw[0] &= (~GENMASK(5, 0));
memcpy(rtw_pattern->mask, mask_hw, RTW_MAX_PATTERN_MASK_SIZE);
/* To get the wake up pattern from the mask.
* We do not count first 12 bits which means
* DA[6] and SA[6] in the pattern to match HW design.
*/
count = 0;
for (i = 12; i < len; i++) {
if ((mask[i / 8] >> (i % 8)) & 0x01) {
content[count] = pattern[i];
count++;
}
}
rtw_pattern->crc = rtw_calc_crc(content, count);
}
static void rtw_wow_pattern_clear_cam(struct rtw_dev *rtwdev)
{
bool ret;
rtw_write32(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 |
BIT_WKFCAM_CLR_V1);
ret = check_hw_ready(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1, 0);
if (!ret)
rtw_err(rtwdev, "failed to clean pattern cam\n");
}
static void rtw_wow_pattern_write(struct rtw_dev *rtwdev)
{
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
struct rtw_wow_pattern *rtw_pattern = rtw_wow->patterns;
int i = 0;
for (i = 0; i < rtw_wow->pattern_cnt; i++)
rtw_wow_pattern_write_cam_ent(rtwdev, i, rtw_pattern + i);
}
static void rtw_wow_pattern_clear(struct rtw_dev *rtwdev)
{
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
rtw_wow_pattern_clear_cam(rtwdev);
rtw_wow->pattern_cnt = 0;
memset(rtw_wow->patterns, 0, sizeof(rtw_wow->patterns));
}
static void rtw_wow_bb_stop(struct rtw_dev *rtwdev)
{
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
/* wait 100ms for firmware to finish TX */
msleep(100);
if (!rtw_read32_mask(rtwdev, REG_BCNQ_INFO, BIT_MGQ_CPU_EMPTY))
rtw_warn(rtwdev, "Wrong status of MGQ_CPU empty!\n");
rtw_wow->txpause = rtw_read8(rtwdev, REG_TXPAUSE);
rtw_write8(rtwdev, REG_TXPAUSE, 0xff);
rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_BB_RSTB);
}
static void rtw_wow_bb_start(struct rtw_dev *rtwdev)
{
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_BB_RSTB);
rtw_write8(rtwdev, REG_TXPAUSE, rtw_wow->txpause);
}
static void rtw_wow_rx_dma_stop(struct rtw_dev *rtwdev)
{
/* wait 100ms for HW to finish rx dma */
msleep(100);
rtw_write32_set(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE);
if (!check_hw_ready(rtwdev, REG_RXPKT_NUM, BIT_RXDMA_IDLE, 1))
rtw_err(rtwdev, "failed to stop rx dma\n");
}
static void rtw_wow_rx_dma_start(struct rtw_dev *rtwdev)
{
rtw_write32_clr(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE);
}
static int rtw_wow_check_fw_status(struct rtw_dev *rtwdev, bool wow_enable)
{
int ret;
u8 check;
u32 check_dis;
if (wow_enable) {
ret = read_poll_timeout(rtw_read8, check, !check, 1000,
100000, true, rtwdev,
REG_WOWLAN_WAKE_REASON);
if (ret)
goto wow_fail;
} else {
ret = read_poll_timeout(rtw_read32_mask, check_dis,
!check_dis, 1000, 100000, true, rtwdev,
REG_FE1IMR, BIT_FS_RXDONE);
if (ret)
goto wow_fail;
ret = read_poll_timeout(rtw_read32_mask, check_dis,
!check_dis, 1000, 100000, false, rtwdev,
REG_RXPKT_NUM, BIT_RW_RELEASE);
if (ret)
goto wow_fail;
}
return 0;
wow_fail:
rtw_err(rtwdev, "failed to check wow status %s\n",
wow_enable ? "enabled" : "disabled");
return -EBUSY;
}
static void rtw_wow_fw_security_type_iter(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
void *data)
{
struct rtw_fw_key_type_iter_data *iter_data = data;
struct rtw_dev *rtwdev = hw->priv;
u8 hw_key_type;
if (vif != rtwdev->wow.wow_vif)
return;
switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
hw_key_type = RTW_CAM_WEP40;
break;
case WLAN_CIPHER_SUITE_WEP104:
hw_key_type = RTW_CAM_WEP104;
break;
case WLAN_CIPHER_SUITE_TKIP:
hw_key_type = RTW_CAM_TKIP;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
break;
case WLAN_CIPHER_SUITE_CCMP:
hw_key_type = RTW_CAM_AES;
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
break;
default:
rtw_err(rtwdev, "Unsupported key type for wowlan mode: %#x\n",
key->cipher);
hw_key_type = 0;
break;
}
if (sta)
iter_data->pairwise_key_type = hw_key_type;
else
iter_data->group_key_type = hw_key_type;
}
static void rtw_wow_fw_security_type(struct rtw_dev *rtwdev)
{
struct rtw_fw_key_type_iter_data data = {};
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
data.rtwdev = rtwdev;
rtw_iterate_keys(rtwdev, wow_vif,
rtw_wow_fw_security_type_iter, &data);
rtw_fw_set_aoac_global_info_cmd(rtwdev, data.pairwise_key_type,
data.group_key_type);
}
static int rtw_wow_fw_start(struct rtw_dev *rtwdev)
{
if (rtw_wow_mgd_linked(rtwdev)) {
rtw_send_rsvd_page_h2c(rtwdev);
rtw_wow_pattern_write(rtwdev);
rtw_wow_fw_security_type(rtwdev);
rtw_fw_set_disconnect_decision_cmd(rtwdev, true);
rtw_fw_set_keep_alive_cmd(rtwdev, true);
} else if (rtw_wow_no_link(rtwdev)) {
rtw_fw_set_nlo_info(rtwdev, true);
rtw_fw_update_pkt_probe_req(rtwdev, NULL);
rtw_fw_channel_switch(rtwdev, true);
}
rtw_fw_set_wowlan_ctrl_cmd(rtwdev, true);
rtw_fw_set_remote_wake_ctrl_cmd(rtwdev, true);
return rtw_wow_check_fw_status(rtwdev, true);
}
static int rtw_wow_fw_stop(struct rtw_dev *rtwdev)
{
if (rtw_wow_mgd_linked(rtwdev)) {
rtw_fw_set_disconnect_decision_cmd(rtwdev, false);
rtw_fw_set_keep_alive_cmd(rtwdev, false);
rtw_wow_pattern_clear(rtwdev);
} else if (rtw_wow_no_link(rtwdev)) {
rtw_fw_channel_switch(rtwdev, false);
rtw_fw_set_nlo_info(rtwdev, false);
}
rtw_fw_set_wowlan_ctrl_cmd(rtwdev, false);
rtw_fw_set_remote_wake_ctrl_cmd(rtwdev, false);
return rtw_wow_check_fw_status(rtwdev, false);
}
static void rtw_wow_avoid_reset_mac(struct rtw_dev *rtwdev)
{
/* When resuming from wowlan mode, some hosts issue signal
* (PCIE: PREST, USB: SE0RST) to device, and lead to reset
* mac core. If it happens, the connection to AP will be lost.
* Setting REG_RSV_CTRL Register can avoid this process.
*/
switch (rtw_hci_type(rtwdev)) {
case RTW_HCI_TYPE_PCIE:
case RTW_HCI_TYPE_USB:
rtw_write8(rtwdev, REG_RSV_CTRL, BIT_WLOCK_1C_B6);
rtw_write8(rtwdev, REG_RSV_CTRL,
BIT_WLOCK_1C_B6 | BIT_R_DIS_PRST);
break;
default:
rtw_warn(rtwdev, "Unsupported hci type to disable reset MAC\n");
break;
}
}
static void rtw_wow_fw_media_status_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
struct rtw_fw_media_status_iter_data *iter_data = data;
struct rtw_dev *rtwdev = iter_data->rtwdev;
rtw_fw_media_status_report(rtwdev, si->mac_id, iter_data->connect);
}
static void rtw_wow_fw_media_status(struct rtw_dev *rtwdev, bool connect)
{
struct rtw_fw_media_status_iter_data data;
data.rtwdev = rtwdev;
data.connect = connect;
rtw_iterate_stas_atomic(rtwdev, rtw_wow_fw_media_status_iter, &data);
}
static int rtw_wow_config_wow_fw_rsvd_page(struct rtw_dev *rtwdev)
{
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
rtw_remove_rsvd_page(rtwdev, rtwvif);
if (rtw_wow_no_link(rtwdev))
rtw_add_rsvd_page_pno(rtwdev, rtwvif);
else
rtw_add_rsvd_page_sta(rtwdev, rtwvif);
return rtw_fw_download_rsvd_page(rtwdev);
}
static int rtw_wow_config_normal_fw_rsvd_page(struct rtw_dev *rtwdev)
{
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
rtw_remove_rsvd_page(rtwdev, rtwvif);
rtw_add_rsvd_page_sta(rtwdev, rtwvif);
if (rtw_wow_no_link(rtwdev))
return 0;
return rtw_fw_download_rsvd_page(rtwdev);
}
static int rtw_wow_swap_fw(struct rtw_dev *rtwdev, enum rtw_fw_type type)
{
struct rtw_fw_state *fw;
int ret;
switch (type) {
case RTW_WOWLAN_FW:
fw = &rtwdev->wow_fw;
break;
case RTW_NORMAL_FW:
fw = &rtwdev->fw;
break;
default:
rtw_warn(rtwdev, "unsupported firmware type to swap\n");
return -ENOENT;
}
ret = rtw_download_firmware(rtwdev, fw);
if (ret)
goto out;
rtw_fw_send_general_info(rtwdev);
rtw_fw_send_phydm_info(rtwdev);
rtw_wow_fw_media_status(rtwdev, true);
out:
return ret;
}
static void rtw_wow_check_pno(struct rtw_dev *rtwdev,
struct cfg80211_sched_scan_request *nd_config)
{
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
struct rtw_pno_request *pno_req = &rtw_wow->pno_req;
struct ieee80211_channel *channel;
int i, size;
if (!nd_config->n_match_sets || !nd_config->n_channels)
goto err;
pno_req->match_set_cnt = nd_config->n_match_sets;
size = sizeof(*pno_req->match_sets) * pno_req->match_set_cnt;
pno_req->match_sets = kmemdup(nd_config->match_sets, size, GFP_KERNEL);
if (!pno_req->match_sets)
goto err;
pno_req->channel_cnt = nd_config->n_channels;
size = sizeof(*nd_config->channels[0]) * nd_config->n_channels;
pno_req->channels = kmalloc(size, GFP_KERNEL);
if (!pno_req->channels)
goto channel_err;
for (i = 0 ; i < pno_req->channel_cnt; i++) {
channel = pno_req->channels + i;
memcpy(channel, nd_config->channels[i], sizeof(*channel));
}
pno_req->scan_plan = *nd_config->scan_plans;
pno_req->inited = true;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: net-detect is enabled\n");
return;
channel_err:
kfree(pno_req->match_sets);
err:
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: net-detect is disabled\n");
}
static int rtw_wow_leave_linked_ps(struct rtw_dev *rtwdev)
{
if (!test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
cancel_delayed_work_sync(&rtwdev->watch_dog_work);
rtw_leave_lps(rtwdev);
return 0;
}
static int rtw_wow_leave_no_link_ps(struct rtw_dev *rtwdev)
{
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
int ret = 0;
if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) {
if (rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
rtw_leave_lps_deep(rtwdev);
} else {
if (test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags)) {
rtw_wow->ips_enabled = true;
ret = rtw_leave_ips(rtwdev);
if (ret)
return ret;
}
}
return 0;
}
static int rtw_wow_leave_ps(struct rtw_dev *rtwdev)
{
int ret = 0;
if (rtw_wow_mgd_linked(rtwdev))
ret = rtw_wow_leave_linked_ps(rtwdev);
else if (rtw_wow_no_link(rtwdev))
ret = rtw_wow_leave_no_link_ps(rtwdev);
return ret;
}
static int rtw_wow_restore_ps(struct rtw_dev *rtwdev)
{
int ret = 0;
if (rtw_wow_no_link(rtwdev) && rtwdev->wow.ips_enabled)
ret = rtw_enter_ips(rtwdev);
return ret;
}
static int rtw_wow_enter_linked_ps(struct rtw_dev *rtwdev)
{
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
rtw_enter_lps(rtwdev, rtwvif->port);
return 0;
}
static int rtw_wow_enter_no_link_ps(struct rtw_dev *rtwdev)
{
/* firmware enters deep ps by itself if supported */
set_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags);
return 0;
}
static int rtw_wow_enter_ps(struct rtw_dev *rtwdev)
{
int ret = 0;
if (rtw_wow_mgd_linked(rtwdev))
ret = rtw_wow_enter_linked_ps(rtwdev);
else if (rtw_wow_no_link(rtwdev) &&
rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
ret = rtw_wow_enter_no_link_ps(rtwdev);
return ret;
}
static void rtw_wow_stop_trx(struct rtw_dev *rtwdev)
{
rtw_wow_bb_stop(rtwdev);
rtw_wow_rx_dma_stop(rtwdev);
}
static int rtw_wow_start(struct rtw_dev *rtwdev)
{
int ret;
ret = rtw_wow_fw_start(rtwdev);
if (ret)
goto out;
rtw_hci_stop(rtwdev);
rtw_wow_bb_start(rtwdev);
rtw_wow_avoid_reset_mac(rtwdev);
out:
return ret;
}
static int rtw_wow_enable(struct rtw_dev *rtwdev)
{
int ret = 0;
rtw_wow_stop_trx(rtwdev);
ret = rtw_wow_swap_fw(rtwdev, RTW_WOWLAN_FW);
if (ret) {
rtw_err(rtwdev, "failed to swap wow fw\n");
goto error;
}
set_bit(RTW_FLAG_WOWLAN, rtwdev->flags);
ret = rtw_wow_config_wow_fw_rsvd_page(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to download wowlan rsvd page\n");
goto error;
}
ret = rtw_wow_start(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to start wow\n");
goto error;
}
return ret;
error:
clear_bit(RTW_FLAG_WOWLAN, rtwdev->flags);
return ret;
}
static int rtw_wow_stop(struct rtw_dev *rtwdev)
{
int ret;
/* some HCI related registers will be reset after resume,
* need to set them again.
*/
ret = rtw_hci_setup(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to setup hci\n");
return ret;
}
ret = rtw_hci_start(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to start hci\n");
return ret;
}
ret = rtw_wow_fw_stop(rtwdev);
if (ret)
rtw_err(rtwdev, "failed to stop wowlan fw\n");
rtw_wow_bb_stop(rtwdev);
return ret;
}
static void rtw_wow_resume_trx(struct rtw_dev *rtwdev)
{
rtw_wow_rx_dma_start(rtwdev);
rtw_wow_bb_start(rtwdev);
ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work,
RTW_WATCH_DOG_DELAY_TIME);
}
static int rtw_wow_disable(struct rtw_dev *rtwdev)
{
int ret;
clear_bit(RTW_FLAG_WOWLAN, rtwdev->flags);
ret = rtw_wow_stop(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to stop wow\n");
goto out;
}
ret = rtw_wow_swap_fw(rtwdev, RTW_NORMAL_FW);
if (ret) {
rtw_err(rtwdev, "failed to swap normal fw\n");
goto out;
}
ret = rtw_wow_config_normal_fw_rsvd_page(rtwdev);
if (ret)
rtw_err(rtwdev, "failed to download normal rsvd page\n");
out:
rtw_wow_resume_trx(rtwdev);
return ret;
}
static void rtw_wow_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct rtw_dev *rtwdev = data;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
/* Current wowlan function support setting of only one STATION vif.
* So when one suitable vif is found, stop the iteration.
*/
if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION)
return;
switch (rtwvif->net_type) {
case RTW_NET_MGD_LINKED:
rtw_wow->wow_vif = vif;
break;
case RTW_NET_NO_LINK:
if (rtw_wow->pno_req.inited)
rtwdev->wow.wow_vif = vif;
break;
default:
break;
}
}
static int rtw_wow_set_wakeups(struct rtw_dev *rtwdev,
struct cfg80211_wowlan *wowlan)
{
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
struct rtw_wow_pattern *rtw_patterns = rtw_wow->patterns;
struct rtw_vif *rtwvif;
int i;
if (wowlan->disconnect)
set_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags);
if (wowlan->magic_pkt)
set_bit(RTW_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags);
if (wowlan->gtk_rekey_failure)
set_bit(RTW_WOW_FLAG_EN_REKEY_PKT, rtw_wow->flags);
if (wowlan->nd_config)
rtw_wow_check_pno(rtwdev, wowlan->nd_config);
rtw_iterate_vifs_atomic(rtwdev, rtw_wow_vif_iter, rtwdev);
if (!rtw_wow->wow_vif)
return -EPERM;
rtwvif = (struct rtw_vif *)rtw_wow->wow_vif->drv_priv;
if (wowlan->n_patterns && wowlan->patterns) {
rtw_wow->pattern_cnt = wowlan->n_patterns;
for (i = 0; i < wowlan->n_patterns; i++)
rtw_wow_pattern_generate(rtwdev, rtwvif,
wowlan->patterns + i,
rtw_patterns + i);
}
return 0;
}
static void rtw_wow_clear_wakeups(struct rtw_dev *rtwdev)
{
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
struct rtw_pno_request *pno_req = &rtw_wow->pno_req;
if (pno_req->inited) {
kfree(pno_req->channels);
kfree(pno_req->match_sets);
}
memset(rtw_wow, 0, sizeof(rtwdev->wow));
}
int rtw_wow_suspend(struct rtw_dev *rtwdev, struct cfg80211_wowlan *wowlan)
{
int ret = 0;
ret = rtw_wow_set_wakeups(rtwdev, wowlan);
if (ret) {
rtw_err(rtwdev, "failed to set wakeup event\n");
goto out;
}
ret = rtw_wow_leave_ps(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to leave ps from normal mode\n");
goto out;
}
ret = rtw_wow_enable(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to enable wow\n");
rtw_wow_restore_ps(rtwdev);
goto out;
}
ret = rtw_wow_enter_ps(rtwdev);
if (ret)
rtw_err(rtwdev, "failed to enter ps for wow\n");
out:
return ret;
}
int rtw_wow_resume(struct rtw_dev *rtwdev)
{
int ret;
/* If wowlan mode is not enabled, do nothing */
if (!test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) {
rtw_err(rtwdev, "wow is not enabled\n");
ret = -EPERM;
goto out;
}
ret = rtw_wow_leave_ps(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to leave ps from wowlan mode\n");
goto out;
}
rtw_wow_show_wakeup_reason(rtwdev);
ret = rtw_wow_disable(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to disable wow\n");
goto out;
}
ret = rtw_wow_restore_ps(rtwdev);
if (ret)
rtw_err(rtwdev, "failed to restore ps to normal mode\n");
out:
rtw_wow_clear_wakeups(rtwdev);
return ret;
}

View File

@ -0,0 +1,58 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW_WOW_H__
#define __RTW_WOW_H__
#define PNO_CHECK_BYTE 4
enum rtw_wow_pattern_type {
RTW_PATTERN_BROADCAST = 0,
RTW_PATTERN_MULTICAST,
RTW_PATTERN_UNICAST,
RTW_PATTERN_VALID,
RTW_PATTERN_INVALID,
};
enum rtw_wake_reason {
RTW_WOW_RSN_RX_PTK_REKEY = 0x1,
RTW_WOW_RSN_RX_GTK_REKEY = 0x2,
RTW_WOW_RSN_RX_DEAUTH = 0x8,
RTW_WOW_RSN_DISCONNECT = 0x10,
RTW_WOW_RSN_RX_MAGIC_PKT = 0x21,
RTW_WOW_RSN_RX_PATTERN_MATCH = 0x23,
RTW_WOW_RSN_RX_NLO = 0x55,
};
struct rtw_fw_media_status_iter_data {
struct rtw_dev *rtwdev;
u8 connect;
};
struct rtw_fw_key_type_iter_data {
struct rtw_dev *rtwdev;
u8 group_key_type;
u8 pairwise_key_type;
};
static inline bool rtw_wow_mgd_linked(struct rtw_dev *rtwdev)
{
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
return (rtwvif->net_type == RTW_NET_MGD_LINKED);
}
static inline bool rtw_wow_no_link(struct rtw_dev *rtwdev)
{
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
return (rtwvif->net_type == RTW_NET_NO_LINK);
}
int rtw_wow_suspend(struct rtw_dev *rtwdev, struct cfg80211_wowlan *wowlan);
int rtw_wow_resume(struct rtw_dev *rtwdev);
#endif

View File

@ -0,0 +1,36 @@
# $FreeBSD$
DEVRTW88DIR= ${SRCTOP}/sys/contrib/dev/rtw88
.PATH: ${DEVRTW88DIR}
WITH_CONFIG_PM= 0
KMOD= if_rtw88
SRCS= main.c
SRCS+= bf.c coex.c debug.c efuse.c fw.c mac.c mac80211.c
SRCS+= pci.c phy.c ps.c regd.c
SRCS+= rtw8723d.c rtw8723d_table.c rtw8723de.c # 11n
SRCS+= rtw8821c.c rtw8821c_table.c rtw8821ce.c # 11ac
SRCS+= rtw8822b.c rtw8822b_table.c rtw8822be.c # 11ac
SRCS+= rtw8822c.c rtw8822c_table.c rtw8822ce.c # 11ac
SRCS+= rx.c sar.c sec.c tx.c util.c
.if defined(WITH_CONFIG_PM) && ${WITH_CONFIG_PM} > 0
SRCR+= wow.c
CFLAGS+= -DCONFIG_PM=${WITH_CONFIG_PM}
.endif
# Other
SRCS+= ${LINUXKPI_GENSRCS}
SRCS+= opt_wlan.h opt_inet6.h opt_inet.h
CFLAGS+= -DKBUILD_MODNAME='"rtw88"'
CFLAGS+= -I${DEVRTW88DIR}
CFLAGS+= -I${SRCTOP}/sys/compat/linuxkpi/common/include
CFLAGS+= -DCONFIG_RTW88_DEBUG
#CFLAGS+= -DCONFIG_RTW88_DEBUGFS
.include <bsd.kmod.mk>