1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-26 07:55:01 +00:00

rtw89: update Realtek's rtw89 driver.

This version is based on
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
98f7e32f20d28ec452afb208f9cffc08448a2652 ( tag: v6.11 ).

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Bjoern A. Zeeb 2024-10-03 23:43:12 +00:00
parent 6224ff21f3
commit 5b760eaecd
75 changed files with 44896 additions and 8101 deletions

19
Kconfig
View File

@ -22,12 +22,18 @@ config RTW89_8851B
config RTW89_8852A
tristate
config RTW89_8852B_COMMON
tristate
config RTW89_8852B
tristate
config RTW89_8852C
tristate
config RTW89_8922A
tristate
config RTW89_8851BE
tristate "Realtek 8851BE PCI wireless network (Wi-Fi 6) adapter"
depends on PCI
@ -56,6 +62,7 @@ config RTW89_8852BE
select RTW89_CORE
select RTW89_PCI
select RTW89_8852B
select RTW89_8852B_COMMON
help
Select this option will enable support for 8852BE chipset
@ -72,6 +79,18 @@ config RTW89_8852CE
802.11ax PCIe wireless network (Wi-Fi 6E) adapter
config RTW89_8922AE
tristate "Realtek 8922AE PCI wireless network (Wi-Fi 7) adapter"
depends on PCI
select RTW89_CORE
select RTW89_PCI
select RTW89_8922A
help
Select this option will enable support for 8922AE chipset
802.11be PCIe wireless network (Wi-Fi 7) adapter
supporting 2x2 2GHz/5GHz/6GHz 4096-QAM 160MHz channels.
config RTW89_DEBUG
bool

View File

@ -4,17 +4,21 @@ obj-$(CONFIG_RTW89_CORE) += rtw89_core.o
rtw89_core-y += core.o \
mac80211.o \
mac.o \
mac_be.o \
phy.o \
phy_be.o \
fw.o \
cam.o \
efuse.o \
efuse_be.o \
regd.o \
sar.o \
coex.o \
ps.o \
chan.o \
ser.o \
acpi.o
acpi.o \
util.o
rtw89_core-$(CONFIG_PM) += wow.o
@ -36,6 +40,9 @@ rtw89_8852a-objs := rtw8852a.o \
obj-$(CONFIG_RTW89_8852AE) += rtw89_8852ae.o
rtw89_8852ae-objs := rtw8852ae.o
obj-$(CONFIG_RTW89_8852B_COMMON) += rtw89_8852b_common.o
rtw89_8852b_common-objs := rtw8852b_common.o
obj-$(CONFIG_RTW89_8852B) += rtw89_8852b.o
rtw89_8852b-objs := rtw8852b.o \
rtw8852b_table.o \
@ -54,8 +61,15 @@ rtw89_8852c-objs := rtw8852c.o \
obj-$(CONFIG_RTW89_8852CE) += rtw89_8852ce.o
rtw89_8852ce-objs := rtw8852ce.o
obj-$(CONFIG_RTW89_8922A) += rtw89_8922a.o
rtw89_8922a-objs := rtw8922a.o \
rtw8922a_rfk.o
obj-$(CONFIG_RTW89_8922AE) += rtw89_8922ae.o
rtw89_8922ae-objs := rtw8922ae.o
rtw89_core-$(CONFIG_RTW89_DEBUG) += debug.o
obj-$(CONFIG_RTW89_PCI) += rtw89_pci.o
rtw89_pci-y := pci.o
rtw89_pci-y := pci.o pci_be.o

128
acpi.c
View File

@ -12,27 +12,118 @@ static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
0x82, 0xBD, 0xFE, 0x86,
0x07, 0x80, 0x3A, 0xA7);
static int rtw89_acpi_dsm_get(struct rtw89_dev *rtwdev, union acpi_object *obj,
u8 *value)
static
int rtw89_acpi_dsm_get_value(struct rtw89_dev *rtwdev, union acpi_object *obj,
u8 *value)
{
switch (obj->type) {
case ACPI_TYPE_INTEGER:
*value = (u8)obj->integer.value;
break;
case ACPI_TYPE_BUFFER:
*value = obj->buffer.pointer[0];
break;
default:
rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
"acpi dsm return unhandled type: %d\n", obj->type);
if (obj->type != ACPI_TYPE_INTEGER) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI,
"acpi: expect integer but type: %d\n", obj->type);
return -EINVAL;
}
*value = (u8)obj->integer.value;
return 0;
}
static bool chk_acpi_policy_6ghz_sig(const struct rtw89_acpi_policy_6ghz *p)
{
return p->signature[0] == 0x00 &&
p->signature[1] == 0xE0 &&
p->signature[2] == 0x4C;
}
static
int rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev *rtwdev,
union acpi_object *obj,
struct rtw89_acpi_policy_6ghz **policy_6ghz)
{
const struct rtw89_acpi_policy_6ghz *ptr;
u32 expect_len;
u32 len;
if (obj->type != ACPI_TYPE_BUFFER) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI,
"acpi: expect buffer but type: %d\n", obj->type);
return -EINVAL;
}
len = obj->buffer.length;
if (len < sizeof(*ptr)) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
__func__, len);
return -EINVAL;
}
ptr = (typeof(ptr))obj->buffer.pointer;
if (!chk_acpi_policy_6ghz_sig(ptr)) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
return -EINVAL;
}
expect_len = struct_size(ptr, country_list, ptr->country_count);
if (len < expect_len) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: expect %u but length: %u\n",
__func__, expect_len, len);
return -EINVAL;
}
*policy_6ghz = kmemdup(ptr, expect_len, GFP_KERNEL);
if (!*policy_6ghz)
return -ENOMEM;
rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz: ", *policy_6ghz,
expect_len);
return 0;
}
static bool chk_acpi_policy_6ghz_sp_sig(const struct rtw89_acpi_policy_6ghz_sp *p)
{
return p->signature[0] == 0x52 &&
p->signature[1] == 0x54 &&
p->signature[2] == 0x4B &&
p->signature[3] == 0x07;
}
static
int rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev *rtwdev,
union acpi_object *obj,
struct rtw89_acpi_policy_6ghz_sp **policy)
{
const struct rtw89_acpi_policy_6ghz_sp *ptr;
u32 buf_len;
if (obj->type != ACPI_TYPE_BUFFER) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI,
"acpi: expect buffer but type: %d\n", obj->type);
return -EINVAL;
}
buf_len = obj->buffer.length;
if (buf_len < sizeof(*ptr)) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
__func__, buf_len);
return -EINVAL;
}
ptr = (typeof(ptr))obj->buffer.pointer;
if (!chk_acpi_policy_6ghz_sp_sig(ptr)) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
return -EINVAL;
}
*policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
if (!*policy)
return -ENOMEM;
rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz_sp: ", *policy,
sizeof(*ptr));
return 0;
}
int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
enum rtw89_acpi_dsm_func func, u8 *value)
enum rtw89_acpi_dsm_func func,
struct rtw89_acpi_dsm_result *res)
{
union acpi_object *obj;
int ret;
@ -40,12 +131,19 @@ int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid,
0, func, NULL);
if (!obj) {
rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
rtw89_debug(rtwdev, RTW89_DBG_ACPI,
"acpi dsm fail to evaluate func: %d\n", func);
return -ENOENT;
}
ret = rtw89_acpi_dsm_get(rtwdev, obj, value);
if (func == RTW89_ACPI_DSM_FUNC_6G_BP)
ret = rtw89_acpi_dsm_get_policy_6ghz(rtwdev, obj,
&res->u.policy_6ghz);
else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP)
ret = rtw89_acpi_dsm_get_policy_6ghz_sp(rtwdev, obj,
&res->u.policy_6ghz_sp);
else
ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value);
ACPI_FREE(obj);
return ret;

53
acpi.h
View File

@ -12,10 +12,59 @@ enum rtw89_acpi_dsm_func {
RTW89_ACPI_DSM_FUNC_6G_DIS = 3,
RTW89_ACPI_DSM_FUNC_6G_BP = 4,
RTW89_ACPI_DSM_FUNC_TAS_EN = 5,
RTW89_ACPI_DSM_FUNC_59G_EN = 6,
RTW89_ACPI_DSM_FUNC_UNII4_SUP = 6,
RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP = 7,
};
enum rtw89_acpi_conf_unii4 {
RTW89_ACPI_CONF_UNII4_FCC = BIT(0),
RTW89_ACPI_CONF_UNII4_IC = BIT(1),
};
enum rtw89_acpi_policy_mode {
RTW89_ACPI_POLICY_BLOCK = 0,
RTW89_ACPI_POLICY_ALLOW = 1,
};
struct rtw89_acpi_country_code {
/* below are allowed:
* * ISO alpha2 country code
* * EU for countries in Europe
*/
char alpha2[2];
} __packed;
struct rtw89_acpi_policy_6ghz {
u8 signature[3];
u8 rsvd;
u8 policy_mode;
u8 country_count;
struct rtw89_acpi_country_code country_list[] __counted_by(country_count);
} __packed;
enum rtw89_acpi_conf_6ghz_sp {
RTW89_ACPI_CONF_6GHZ_SP_US = BIT(0),
};
struct rtw89_acpi_policy_6ghz_sp {
u8 signature[4];
u8 revision;
u8 override;
u8 conf;
u8 rsvd;
} __packed;
struct rtw89_acpi_dsm_result {
union {
u8 value;
/* caller needs to free it after using */
struct rtw89_acpi_policy_6ghz *policy_6ghz;
struct rtw89_acpi_policy_6ghz_sp *policy_6ghz_sp;
} u;
};
int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
enum rtw89_acpi_dsm_func func, u8 *value);
enum rtw89_acpi_dsm_func func,
struct rtw89_acpi_dsm_result *res);
#endif

273
cam.c
View File

@ -150,8 +150,6 @@ static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam,
case RTW89_ADDR_CAM_SEC_NONE:
return -EINVAL;
case RTW89_ADDR_CAM_SEC_ALL_UNI:
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
return -EINVAL;
idx = find_first_zero_bit(addr_cam->sec_cam_map,
RTW89_SEC_CAM_IN_ADDR_CAM);
if (idx >= RTW89_SEC_CAM_IN_ADDR_CAM)
@ -213,6 +211,46 @@ static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam,
return 0;
}
static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
const struct rtw89_sec_cam_entry *sec_cam,
bool inform_fw)
{
struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
struct rtw89_vif *rtwvif;
struct rtw89_addr_cam_entry *addr_cam;
unsigned int i;
int ret = 0;
if (!vif) {
rtw89_err(rtwdev, "No iface for deleting sec cam\n");
return -EINVAL;
}
rtwvif = (struct rtw89_vif *)vif->drv_priv;
addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) {
if (addr_cam->sec_ent[i] != sec_cam->sec_cam_idx)
continue;
clear_bit(i, addr_cam->sec_cam_map);
}
if (inform_fw) {
ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
if (ret)
rtw89_err(rtwdev,
"failed to update dctl cam del key: %d\n", ret);
ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
if (ret)
rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret);
}
return ret;
}
static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@ -232,6 +270,11 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
rtwvif = (struct rtw89_vif *)vif->drv_priv;
addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
key->cipher == WLAN_CIPHER_SUITE_WEP104)
addr_cam->sec_ent_mode = RTW89_ADDR_CAM_SEC_ALL_UNI;
ret = rtw89_cam_get_addr_cam_key_idx(addr_cam, sec_cam, key, &key_idx);
if (ret) {
rtw89_err(rtwdev, "failed to get addr cam key idx %d, %d\n",
@ -239,10 +282,8 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
return ret;
}
key->hw_key_idx = key_idx;
addr_cam->sec_ent_keyid[key_idx] = key->keyidx;
addr_cam->sec_ent[key_idx] = sec_cam->sec_cam_idx;
addr_cam->sec_entries[key_idx] = sec_cam;
set_bit(key_idx, addr_cam->sec_cam_map);
ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
if (ret) {
@ -255,7 +296,6 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n",
ret);
clear_bit(key_idx, addr_cam->sec_cam_map);
addr_cam->sec_entries[key_idx] = NULL;
return ret;
}
@ -292,6 +332,9 @@ static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev,
goto err_release_cam;
}
key->hw_key_idx = sec_cam_idx;
cam_info->sec_entries[sec_cam_idx] = sec_cam;
sec_cam->sec_cam_idx = sec_cam_idx;
sec_cam->type = hw_key_type;
sec_cam->len = RTW89_SEC_CAM_LEN;
@ -313,6 +356,7 @@ static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev,
return 0;
err_release_cam:
cam_info->sec_entries[sec_cam_idx] = NULL;
kfree(sec_cam);
clear_bit(sec_cam_idx, cam_info->sec_cam_map);
if (ext_key)
@ -356,6 +400,9 @@ int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
ext_key = true;
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
hw_key_type = RTW89_SEC_KEY_TYPE_BIP_CCMP128;
break;
default:
return -EOPNOTSUPP;
}
@ -380,42 +427,22 @@ int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev,
struct ieee80211_key_conf *key,
bool inform_fw)
{
struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
struct rtw89_vif *rtwvif;
struct rtw89_addr_cam_entry *addr_cam;
struct rtw89_sec_cam_entry *sec_cam;
u8 key_idx = key->hw_key_idx;
const struct rtw89_sec_cam_entry *sec_cam;
u8 sec_cam_idx;
int ret = 0;
int ret;
if (!vif) {
rtw89_err(rtwdev, "No iface for deleting sec cam\n");
return -EINVAL;
}
rtwvif = (struct rtw89_vif *)vif->drv_priv;
addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
sec_cam = addr_cam->sec_entries[key_idx];
sec_cam_idx = key->hw_key_idx;
sec_cam = cam_info->sec_entries[sec_cam_idx];
if (!sec_cam)
return -EINVAL;
/* detach sec cam from addr cam */
clear_bit(key_idx, addr_cam->sec_cam_map);
addr_cam->sec_entries[key_idx] = NULL;
if (inform_fw) {
ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
if (ret)
rtw89_err(rtwdev, "failed to update dctl cam del key: %d\n", ret);
ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
if (ret)
rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret);
}
ret = rtw89_cam_detach_sec_cam(rtwdev, vif, sta, sec_cam, inform_fw);
/* clear valid bit in addr cam will disable sec cam,
* so we don't need to send H2C command again
*/
sec_cam_idx = sec_cam->sec_cam_idx;
cam_info->sec_entries[sec_cam_idx] = NULL;
clear_bit(sec_cam_idx, cam_info->sec_cam_map);
if (sec_cam->ext_key)
clear_bit(sec_cam_idx + 1, cam_info->sec_cam_map);
@ -488,6 +515,21 @@ static int rtw89_cam_get_avail_addr_cam(struct rtw89_dev *rtwdev,
return 0;
}
static u8 rtw89_get_addr_cam_entry_size(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
switch (chip->chip_id) {
case RTL8852A:
case RTL8852B:
case RTL8851B:
case RTL8852BT:
return ADDR_CAM_ENT_SIZE;
default:
return ADDR_CAM_ENT_SHORT_SIZE;
}
}
int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
struct rtw89_addr_cam_entry *addr_cam,
const struct rtw89_bssid_cam_entry *bssid_cam)
@ -509,7 +551,7 @@ int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
}
addr_cam->addr_cam_idx = addr_cam_idx;
addr_cam->len = ADDR_CAM_ENT_SIZE;
addr_cam->len = rtw89_get_addr_cam_entry_size(rtwdev);
addr_cam->offset = 0;
addr_cam->valid = true;
addr_cam->addr_mask = 0;
@ -739,27 +781,158 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif,
struct rtw89_sta *rtwsta,
u8 *cmd)
struct rtw89_h2c_dctlinfo_ud_v1 *h2c)
{
struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv;
SET_DCTL_MACID_V1(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id);
SET_DCTL_OPERATION_V1(cmd, 1);
h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id,
DCTLINFO_V1_C0_MACID) |
le32_encode_bits(1, DCTLINFO_V1_C0_OP);
SET_DCTL_SEC_ENT0_KEYID_V1(cmd, addr_cam->sec_ent_keyid[0]);
SET_DCTL_SEC_ENT1_KEYID_V1(cmd, addr_cam->sec_ent_keyid[1]);
SET_DCTL_SEC_ENT2_KEYID_V1(cmd, addr_cam->sec_ent_keyid[2]);
SET_DCTL_SEC_ENT3_KEYID_V1(cmd, addr_cam->sec_ent_keyid[3]);
SET_DCTL_SEC_ENT4_KEYID_V1(cmd, addr_cam->sec_ent_keyid[4]);
SET_DCTL_SEC_ENT5_KEYID_V1(cmd, addr_cam->sec_ent_keyid[5]);
SET_DCTL_SEC_ENT6_KEYID_V1(cmd, addr_cam->sec_ent_keyid[6]);
h2c->w4 = le32_encode_bits(addr_cam->sec_ent_keyid[0],
DCTLINFO_V1_W4_SEC_ENT0_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[1],
DCTLINFO_V1_W4_SEC_ENT1_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[2],
DCTLINFO_V1_W4_SEC_ENT2_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[3],
DCTLINFO_V1_W4_SEC_ENT3_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[4],
DCTLINFO_V1_W4_SEC_ENT4_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[5],
DCTLINFO_V1_W4_SEC_ENT5_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[6],
DCTLINFO_V1_W4_SEC_ENT6_KEYID);
h2c->m4 = cpu_to_le32(DCTLINFO_V1_W4_SEC_ENT0_KEYID |
DCTLINFO_V1_W4_SEC_ENT1_KEYID |
DCTLINFO_V1_W4_SEC_ENT2_KEYID |
DCTLINFO_V1_W4_SEC_ENT3_KEYID |
DCTLINFO_V1_W4_SEC_ENT4_KEYID |
DCTLINFO_V1_W4_SEC_ENT5_KEYID |
DCTLINFO_V1_W4_SEC_ENT6_KEYID);
SET_DCTL_SEC_ENT_VALID_V1(cmd, addr_cam->sec_cam_map[0] & 0xff);
SET_DCTL_SEC_ENT0_V1(cmd, addr_cam->sec_ent[0]);
SET_DCTL_SEC_ENT1_V1(cmd, addr_cam->sec_ent[1]);
SET_DCTL_SEC_ENT2_V1(cmd, addr_cam->sec_ent[2]);
SET_DCTL_SEC_ENT3_V1(cmd, addr_cam->sec_ent[3]);
SET_DCTL_SEC_ENT4_V1(cmd, addr_cam->sec_ent[4]);
SET_DCTL_SEC_ENT5_V1(cmd, addr_cam->sec_ent[5]);
SET_DCTL_SEC_ENT6_V1(cmd, addr_cam->sec_ent[6]);
h2c->w5 = le32_encode_bits(addr_cam->sec_cam_map[0] & 0xff,
DCTLINFO_V1_W5_SEC_ENT_VALID) |
le32_encode_bits(addr_cam->sec_ent[0],
DCTLINFO_V1_W5_SEC_ENT0) |
le32_encode_bits(addr_cam->sec_ent[1],
DCTLINFO_V1_W5_SEC_ENT1) |
le32_encode_bits(addr_cam->sec_ent[2],
DCTLINFO_V1_W5_SEC_ENT2);
h2c->m5 = cpu_to_le32(DCTLINFO_V1_W5_SEC_ENT_VALID |
DCTLINFO_V1_W5_SEC_ENT0 |
DCTLINFO_V1_W5_SEC_ENT1 |
DCTLINFO_V1_W5_SEC_ENT2);
h2c->w6 = le32_encode_bits(addr_cam->sec_ent[3],
DCTLINFO_V1_W6_SEC_ENT3) |
le32_encode_bits(addr_cam->sec_ent[4],
DCTLINFO_V1_W6_SEC_ENT4) |
le32_encode_bits(addr_cam->sec_ent[5],
DCTLINFO_V1_W6_SEC_ENT5) |
le32_encode_bits(addr_cam->sec_ent[6],
DCTLINFO_V1_W6_SEC_ENT6);
h2c->m6 = cpu_to_le32(DCTLINFO_V1_W6_SEC_ENT3 |
DCTLINFO_V1_W6_SEC_ENT4 |
DCTLINFO_V1_W6_SEC_ENT5 |
DCTLINFO_V1_W6_SEC_ENT6);
if (rtw_wow->ptk_alg) {
h2c->w0 = le32_encode_bits(ptk_tx_iv[0] | ptk_tx_iv[1] << 8,
DCTLINFO_V1_W0_AES_IV_L);
h2c->m0 = cpu_to_le32(DCTLINFO_V1_W0_AES_IV_L);
h2c->w1 = le32_encode_bits(ptk_tx_iv[4] |
ptk_tx_iv[5] << 8 |
ptk_tx_iv[6] << 16 |
ptk_tx_iv[7] << 24,
DCTLINFO_V1_W1_AES_IV_H);
h2c->m1 = cpu_to_le32(DCTLINFO_V1_W1_AES_IV_H);
h2c->w4 |= le32_encode_bits(rtw_wow->ptk_keyidx,
DCTLINFO_V1_W4_SEC_KEY_ID);
h2c->m4 |= cpu_to_le32(DCTLINFO_V1_W4_SEC_KEY_ID);
}
}
void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif,
struct rtw89_sta *rtwsta,
struct rtw89_h2c_dctlinfo_ud_v2 *h2c)
{
struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv;
h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id,
DCTLINFO_V2_C0_MACID) |
le32_encode_bits(1, DCTLINFO_V2_C0_OP);
h2c->w4 = le32_encode_bits(addr_cam->sec_ent_keyid[0],
DCTLINFO_V2_W4_SEC_ENT0_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[1],
DCTLINFO_V2_W4_SEC_ENT1_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[2],
DCTLINFO_V2_W4_SEC_ENT2_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[3],
DCTLINFO_V2_W4_SEC_ENT3_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[4],
DCTLINFO_V2_W4_SEC_ENT4_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[5],
DCTLINFO_V2_W4_SEC_ENT5_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[6],
DCTLINFO_V2_W4_SEC_ENT6_KEYID);
h2c->m4 = cpu_to_le32(DCTLINFO_V2_W4_SEC_ENT0_KEYID |
DCTLINFO_V2_W4_SEC_ENT1_KEYID |
DCTLINFO_V2_W4_SEC_ENT2_KEYID |
DCTLINFO_V2_W4_SEC_ENT3_KEYID |
DCTLINFO_V2_W4_SEC_ENT4_KEYID |
DCTLINFO_V2_W4_SEC_ENT5_KEYID |
DCTLINFO_V2_W4_SEC_ENT6_KEYID);
h2c->w5 = le32_encode_bits(addr_cam->sec_cam_map[0],
DCTLINFO_V2_W5_SEC_ENT_VALID_V1) |
le32_encode_bits(addr_cam->sec_ent[0],
DCTLINFO_V2_W5_SEC_ENT0_V1);
h2c->m5 = cpu_to_le32(DCTLINFO_V2_W5_SEC_ENT_VALID_V1 |
DCTLINFO_V2_W5_SEC_ENT0_V1);
h2c->w6 = le32_encode_bits(addr_cam->sec_ent[1],
DCTLINFO_V2_W6_SEC_ENT1_V1) |
le32_encode_bits(addr_cam->sec_ent[2],
DCTLINFO_V2_W6_SEC_ENT2_V1) |
le32_encode_bits(addr_cam->sec_ent[3],
DCTLINFO_V2_W6_SEC_ENT3_V1) |
le32_encode_bits(addr_cam->sec_ent[4],
DCTLINFO_V2_W6_SEC_ENT4_V1);
h2c->m6 = cpu_to_le32(DCTLINFO_V2_W6_SEC_ENT1_V1 |
DCTLINFO_V2_W6_SEC_ENT2_V1 |
DCTLINFO_V2_W6_SEC_ENT3_V1 |
DCTLINFO_V2_W6_SEC_ENT4_V1);
h2c->w7 = le32_encode_bits(addr_cam->sec_ent[5],
DCTLINFO_V2_W7_SEC_ENT5_V1) |
le32_encode_bits(addr_cam->sec_ent[6],
DCTLINFO_V2_W7_SEC_ENT6_V1);
h2c->m7 = cpu_to_le32(DCTLINFO_V2_W7_SEC_ENT5_V1 |
DCTLINFO_V2_W7_SEC_ENT6_V1);
if (rtw_wow->ptk_alg) {
h2c->w0 = le32_encode_bits(ptk_tx_iv[0] | ptk_tx_iv[1] << 8,
DCTLINFO_V2_W0_AES_IV_L);
h2c->m0 = cpu_to_le32(DCTLINFO_V2_W0_AES_IV_L);
h2c->w1 = le32_encode_bits(ptk_tx_iv[4] |
ptk_tx_iv[5] << 8 |
ptk_tx_iv[6] << 16 |
ptk_tx_iv[7] << 24,
DCTLINFO_V2_W1_AES_IV_H);
h2c->m1 = cpu_to_le32(DCTLINFO_V2_W1_AES_IV_H);
h2c->w4 |= le32_encode_bits(rtw_wow->ptk_keyidx,
DCTLINFO_V2_W4_SEC_KEY_ID);
h2c->m4 |= cpu_to_le32(DCTLINFO_V2_W4_SEC_KEY_ID);
}
}

180
cam.h
View File

@ -352,6 +352,180 @@ static inline void FWCMD_SET_ADDR_BSSID_BSSID5(void *cmd, u32 value)
le32p_replace_bits((__le32 *)(cmd) + 14, value, GENMASK(31, 24));
}
struct rtw89_h2c_dctlinfo_ud_v1 {
__le32 c0;
__le32 w0;
__le32 w1;
__le32 w2;
__le32 w3;
__le32 w4;
__le32 w5;
__le32 w6;
__le32 w7;
__le32 m0;
__le32 m1;
__le32 m2;
__le32 m3;
__le32 m4;
__le32 m5;
__le32 m6;
__le32 m7;
} __packed;
#define DCTLINFO_V1_C0_MACID GENMASK(6, 0)
#define DCTLINFO_V1_C0_OP BIT(7)
#define DCTLINFO_V1_W0_QOS_FIELD_H GENMASK(7, 0)
#define DCTLINFO_V1_W0_HW_EXSEQ_MACID GENMASK(14, 8)
#define DCTLINFO_V1_W0_QOS_DATA BIT(15)
#define DCTLINFO_V1_W0_AES_IV_L GENMASK(31, 16)
#define DCTLINFO_V1_W0_ALL GENMASK(31, 0)
#define DCTLINFO_V1_W1_AES_IV_H GENMASK(31, 0)
#define DCTLINFO_V1_W1_ALL GENMASK(31, 0)
#define DCTLINFO_V1_W2_SEQ0 GENMASK(11, 0)
#define DCTLINFO_V1_W2_SEQ1 GENMASK(23, 12)
#define DCTLINFO_V1_W2_AMSDU_MAX_LEN GENMASK(26, 24)
#define DCTLINFO_V1_W2_STA_AMSDU_EN BIT(27)
#define DCTLINFO_V1_W2_CHKSUM_OFLD_EN BIT(28)
#define DCTLINFO_V1_W2_WITH_LLC BIT(29)
#define DCTLINFO_V1_W2_ALL GENMASK(29, 0)
#define DCTLINFO_V1_W3_SEQ2 GENMASK(11, 0)
#define DCTLINFO_V1_W3_SEQ3 GENMASK(23, 12)
#define DCTLINFO_V1_W3_TGT_IND GENMASK(27, 24)
#define DCTLINFO_V1_W3_TGT_IND_EN BIT(28)
#define DCTLINFO_V1_W3_HTC_LB GENMASK(31, 29)
#define DCTLINFO_V1_W3_ALL GENMASK(31, 0)
#define DCTLINFO_V1_W4_MHDR_LEN GENMASK(4, 0)
#define DCTLINFO_V1_W4_VLAN_TAG_VALID BIT(5)
#define DCTLINFO_V1_W4_VLAN_TAG_SEL GENMASK(7, 6)
#define DCTLINFO_V1_W4_HTC_ORDER BIT(8)
#define DCTLINFO_V1_W4_SEC_KEY_ID GENMASK(10, 9)
#define DCTLINFO_V1_W4_WAPI BIT(15)
#define DCTLINFO_V1_W4_SEC_ENT_MODE GENMASK(17, 16)
#define DCTLINFO_V1_W4_SEC_ENT0_KEYID GENMASK(19, 18)
#define DCTLINFO_V1_W4_SEC_ENT1_KEYID GENMASK(21, 20)
#define DCTLINFO_V1_W4_SEC_ENT2_KEYID GENMASK(23, 22)
#define DCTLINFO_V1_W4_SEC_ENT3_KEYID GENMASK(25, 24)
#define DCTLINFO_V1_W4_SEC_ENT4_KEYID GENMASK(27, 26)
#define DCTLINFO_V1_W4_SEC_ENT5_KEYID GENMASK(29, 28)
#define DCTLINFO_V1_W4_SEC_ENT6_KEYID GENMASK(31, 30)
#define DCTLINFO_V1_W4_ALL (GENMASK(31, 15) | GENMASK(10, 0))
#define DCTLINFO_V1_W5_SEC_ENT_VALID GENMASK(7, 0)
#define DCTLINFO_V1_W5_SEC_ENT0 GENMASK(15, 8)
#define DCTLINFO_V1_W5_SEC_ENT1 GENMASK(23, 16)
#define DCTLINFO_V1_W5_SEC_ENT2 GENMASK(31, 24)
#define DCTLINFO_V1_W5_ALL GENMASK(31, 0)
#define DCTLINFO_V1_W6_SEC_ENT3 GENMASK(7, 0)
#define DCTLINFO_V1_W6_SEC_ENT4 GENMASK(15, 8)
#define DCTLINFO_V1_W6_SEC_ENT5 GENMASK(23, 16)
#define DCTLINFO_V1_W6_SEC_ENT6 GENMASK(31, 24)
#define DCTLINFO_V1_W6_ALL GENMASK(31, 0)
struct rtw89_h2c_dctlinfo_ud_v2 {
__le32 c0;
__le32 w0;
__le32 w1;
__le32 w2;
__le32 w3;
__le32 w4;
__le32 w5;
__le32 w6;
__le32 w7;
__le32 w8;
__le32 w9;
__le32 w10;
__le32 w11;
__le32 w12;
__le32 w13;
__le32 w14;
__le32 w15;
__le32 m0;
__le32 m1;
__le32 m2;
__le32 m3;
__le32 m4;
__le32 m5;
__le32 m6;
__le32 m7;
__le32 m8;
__le32 m9;
__le32 m10;
__le32 m11;
__le32 m12;
__le32 m13;
__le32 m14;
__le32 m15;
} __packed;
#define DCTLINFO_V2_C0_MACID GENMASK(6, 0)
#define DCTLINFO_V2_C0_OP BIT(7)
#define DCTLINFO_V2_W0_QOS_FIELD_H GENMASK(7, 0)
#define DCTLINFO_V2_W0_HW_EXSEQ_MACID GENMASK(14, 8)
#define DCTLINFO_V2_W0_QOS_DATA BIT(15)
#define DCTLINFO_V2_W0_AES_IV_L GENMASK(31, 16)
#define DCTLINFO_V2_W0_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W1_AES_IV_H GENMASK(31, 0)
#define DCTLINFO_V2_W1_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W2_SEQ0 GENMASK(11, 0)
#define DCTLINFO_V2_W2_SEQ1 GENMASK(23, 12)
#define DCTLINFO_V2_W2_AMSDU_MAX_LEN GENMASK(26, 24)
#define DCTLINFO_V2_W2_STA_AMSDU_EN BIT(27)
#define DCTLINFO_V2_W2_CHKSUM_OFLD_EN BIT(28)
#define DCTLINFO_V2_W2_WITH_LLC BIT(29)
#define DCTLINFO_V2_W2_NAT25_EN BIT(30)
#define DCTLINFO_V2_W2_IS_MLD BIT(31)
#define DCTLINFO_V2_W2_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W3_SEQ2 GENMASK(11, 0)
#define DCTLINFO_V2_W3_SEQ3 GENMASK(23, 12)
#define DCTLINFO_V2_W3_TGT_IND GENMASK(27, 24)
#define DCTLINFO_V2_W3_TGT_IND_EN BIT(28)
#define DCTLINFO_V2_W3_HTC_LB GENMASK(31, 29)
#define DCTLINFO_V2_W3_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W4_VLAN_TAG_SEL GENMASK(7, 5)
#define DCTLINFO_V2_W4_HTC_ORDER BIT(8)
#define DCTLINFO_V2_W4_SEC_KEY_ID GENMASK(10, 9)
#define DCTLINFO_V2_W4_VLAN_RX_DYNAMIC_PCP_EN BIT(11)
#define DCTLINFO_V2_W4_VLAN_RX_PKT_DROP BIT(12)
#define DCTLINFO_V2_W4_VLAN_RX_VALID BIT(13)
#define DCTLINFO_V2_W4_VLAN_TX_VALID BIT(14)
#define DCTLINFO_V2_W4_WAPI BIT(15)
#define DCTLINFO_V2_W4_SEC_ENT_MODE GENMASK(17, 16)
#define DCTLINFO_V2_W4_SEC_ENT0_KEYID GENMASK(19, 18)
#define DCTLINFO_V2_W4_SEC_ENT1_KEYID GENMASK(21, 20)
#define DCTLINFO_V2_W4_SEC_ENT2_KEYID GENMASK(23, 22)
#define DCTLINFO_V2_W4_SEC_ENT3_KEYID GENMASK(25, 24)
#define DCTLINFO_V2_W4_SEC_ENT4_KEYID GENMASK(27, 26)
#define DCTLINFO_V2_W4_SEC_ENT5_KEYID GENMASK(29, 28)
#define DCTLINFO_V2_W4_SEC_ENT6_KEYID GENMASK(31, 30)
#define DCTLINFO_V2_W4_ALL GENMASK(31, 5)
#define DCTLINFO_V2_W5_SEC_ENT7_KEYID GENMASK(1, 0)
#define DCTLINFO_V2_W5_SEC_ENT8_KEYID GENMASK(3, 2)
#define DCTLINFO_V2_W5_SEC_ENT_VALID_V1 GENMASK(23, 8)
#define DCTLINFO_V2_W5_SEC_ENT0_V1 GENMASK(31, 24)
#define DCTLINFO_V2_W5_ALL (GENMASK(31, 8) | GENMASK(3, 0))
#define DCTLINFO_V2_W6_SEC_ENT1_V1 GENMASK(7, 0)
#define DCTLINFO_V2_W6_SEC_ENT2_V1 GENMASK(15, 8)
#define DCTLINFO_V2_W6_SEC_ENT3_V1 GENMASK(23, 16)
#define DCTLINFO_V2_W6_SEC_ENT4_V1 GENMASK(31, 24)
#define DCTLINFO_V2_W6_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W7_SEC_ENT5_V1 GENMASK(7, 0)
#define DCTLINFO_V2_W7_SEC_ENT6_V1 GENMASK(15, 8)
#define DCTLINFO_V2_W7_SEC_ENT7 GENMASK(23, 16)
#define DCTLINFO_V2_W7_SEC_ENT8 GENMASK(31, 24)
#define DCTLINFO_V2_W7_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W8_MLD_SMA_L_V1 GENMASK(31, 0)
#define DCTLINFO_V2_W8_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W9_MLD_SMA_H_V1 GENMASK(15, 0)
#define DCTLINFO_V2_W9_MLD_TMA_L_V1 GENMASK(31, 16)
#define DCTLINFO_V2_W9_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W10_MLD_TMA_H_V1 GENMASK(31, 0)
#define DCTLINFO_V2_W10_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W11_MLD_TA_BSSID_L_V1 GENMASK(31, 0)
#define DCTLINFO_V2_W11_ALL GENMASK(31, 0)
#define DCTLINFO_V2_W12_MLD_TA_BSSID_H_V1 GENMASK(15, 0)
#define DCTLINFO_V2_W12_ALL GENMASK(15, 0)
int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
@ -372,7 +546,11 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif,
struct rtw89_sta *rtwsta,
u8 *cmd);
struct rtw89_h2c_dctlinfo_ud_v1 *h2c);
void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif,
struct rtw89_sta *rtwsta,
struct rtw89_h2c_dctlinfo_ud_v2 *h2c);
int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif,
struct rtw89_sta *rtwsta, u8 *cmd);

2265
chan.c

File diff suppressed because it is too large Load Diff

48
chan.h
View File

@ -7,6 +7,42 @@
#include "core.h"
/* The dwell time in TU before doing rtw89_chanctx_work(). */
#define RTW89_CHANCTX_TIME_MCC_PREPARE 100
#define RTW89_CHANCTX_TIME_MCC 100
/* various MCC setting time in TU */
#define RTW89_MCC_LONG_TRIGGER_TIME 300
#define RTW89_MCC_SHORT_TRIGGER_TIME 100
#define RTW89_MCC_EARLY_TX_BCN_TIME 10
#define RTW89_MCC_EARLY_RX_BCN_TIME 5
#define RTW89_MCC_MIN_RX_BCN_TIME 10
#define RTW89_MCC_DFLT_BCN_OFST_TIME 40
#define RTW89_MCC_MIN_GO_DURATION \
(RTW89_MCC_EARLY_TX_BCN_TIME + RTW89_MCC_MIN_RX_BCN_TIME)
#define RTW89_MCC_MIN_STA_DURATION \
(RTW89_MCC_EARLY_RX_BCN_TIME + RTW89_MCC_MIN_RX_BCN_TIME)
#define RTW89_MCC_DFLT_GROUP 0
#define RTW89_MCC_NEXT_GROUP(cur) (((cur) + 1) % 4)
#define RTW89_MCC_DFLT_TX_NULL_EARLY 3
#define RTW89_MCC_DFLT_COURTESY_SLOT 3
#define NUM_OF_RTW89_MCC_ROLES 2
enum rtw89_chanctx_pause_reasons {
RTW89_CHANCTX_PAUSE_REASON_HW_SCAN,
RTW89_CHANCTX_PAUSE_REASON_ROC,
};
struct rtw89_entity_weight {
unsigned int active_chanctxs;
unsigned int active_roles;
};
static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
@ -42,6 +78,10 @@ void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
enum rtw89_sub_entity_idx idx,
const struct rtw89_chan *new);
int rtw89_iterate_entity_chan(struct rtw89_dev *rtwdev,
int (*iterator)(const struct rtw89_chan *chan,
void *data),
void *data);
void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
enum rtw89_sub_entity_idx idx,
const struct cfg80211_chan_def *chandef);
@ -50,6 +90,14 @@ void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
const struct cfg80211_chan_def *chandef);
void rtw89_entity_init(struct rtw89_dev *rtwdev);
enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev);
void rtw89_chanctx_work(struct work_struct *work);
void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev);
void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_changes change);
void rtw89_chanctx_track(struct rtw89_dev *rtwdev);
void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_pause_reasons rsn);
void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev);
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx);
void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,

2980
coex.c

File diff suppressed because it is too large Load Diff

176
coex.h
View File

@ -7,6 +7,10 @@
#include "core.h"
#define BTC_H2C_MAXLEN 2020
#define BTC_TLV_SLOT_ID_LEN_V7 1
#define BTC_SLOT_REQ_TH 2
enum btc_mode {
BTC_MODE_NORMAL,
BTC_MODE_WL,
@ -23,6 +27,7 @@ enum btc_wl_rfk_type {
BTC_WRFKT_DACK = 4,
BTC_WRFKT_RXDCK = 5,
BTC_WRFKT_TSSI = 6,
BTC_WRFKT_CHLK = 7,
};
#define NM_EXEC false
@ -142,6 +147,116 @@ enum btc_lps_state {
BTC_LPS_RF_ON = 2
};
#define R_BTC_BB_BTG_RX 0x980
#define R_BTC_BB_PRE_AGC_S1 0x476C
#define R_BTC_BB_PRE_AGC_S0 0x4688
#define B_BTC_BB_GNT_MUX GENMASK(20, 17)
#define B_BTC_BB_PRE_AGC_MASK GENMASK(31, 24)
#define B_BTC_BB_PRE_AGC_VAL BIT(31)
#define BTC_REG_NOTFOUND 0xff
#define R_BTC_ZB_COEX_TBL_0 0xE328
#define R_BTC_ZB_COEX_TBL_1 0xE32c
#define R_BTC_ZB_BREAK_TBL 0xE350
enum btc_ant_div_pos {
BTC_ANT_DIV_MAIN = 0,
BTC_ANT_DIV_AUX = 1,
};
enum btc_get_reg_status {
BTC_CSTATUS_TXDIV_POS = 0,
BTC_CSTATUS_RXDIV_POS = 1,
BTC_CSTATUS_BB_GNT_MUX = 2,
BTC_CSTATUS_BB_GNT_MUX_MON = 3,
BTC_CSTATUS_BB_PRE_AGC = 4,
BTC_CSTATUS_BB_PRE_AGC_MON = 5,
};
enum btc_preagc_type {
BTC_PREAGC_DISABLE,
BTC_PREAGC_ENABLE,
BTC_PREAGC_BB_FWCTRL,
BTC_PREAGC_NOTFOUND,
};
enum btc_btgctrl_type {
BTC_BTGCTRL_DISABLE,
BTC_BTGCTRL_ENABLE,
BTC_BTGCTRL_BB_GNT_FWCTRL,
BTC_BTGCTRL_BB_GNT_NOTFOUND,
};
enum btc_wa_type {
BTC_WA_5G_HI_CH_RX = BIT(0),
BTC_WA_NULL_AP = BIT(1),
BTC_WA_HFP_ZB = BIT(2), /* HFP PTA req bit4 define issue */
};
enum btc_3cx_type {
BTC_3CX_NONE = 0,
BTC_3CX_BT2 = BIT(0),
BTC_3CX_ZB = BIT(1),
BTC_3CX_LTE = BIT(2),
BTC_3CX_MAX,
};
enum btc_chip_feature {
BTC_FEAT_PTA_ONOFF_CTRL = BIT(0), /* on/off ctrl by HW (not 0x73[2]) */
BTC_FEAT_NONBTG_GWL_THRU = BIT(1), /* non-BTG GNT_WL!=0 if GNT_BT = 1 */
BTC_FEAT_WLAN_ACT_MUX = BIT(2), /* separate wlan_act/gnt mux */
BTC_FEAT_NEW_BBAPI_FLOW = BIT(3), /* new btg_ctrl/pre_agc_ctrl */
BTC_FEAT_MLO_SUPPORT = BIT(4),
BTC_FEAT_H2C_MACRO = BIT(5),
};
enum btc_wl_mode {
BTC_WL_MODE_11B = 0,
BTC_WL_MODE_11A = 1,
BTC_WL_MODE_11G = 2,
BTC_WL_MODE_HT = 3,
BTC_WL_MODE_VHT = 4,
BTC_WL_MODE_HE = 5,
BTC_WL_MODE_NUM,
};
enum btc_wl_gpio_debug {
BTC_DBG_GNT_BT = 0,
BTC_DBG_GNT_WL = 1,
BTC_DBG_BCN_EARLY = 2,
BTC_DBG_WL_NULL0 = 3,
BTC_DBG_WL_NULL1 = 4,
BTC_DBG_WL_RXISR = 5,
BTC_DBG_TDMA_ENTRY = 6,
BTC_DBG_A2DP_EMPTY = 7,
BTC_DBG_BT_RETRY = 8,
BTC_DBG_BT_RELINK = 9,
BTC_DBG_SLOT_WL = 10,
BTC_DBG_SLOT_BT = 11,
BTC_DBG_WL_ERR = 12,
BTC_DBG_WL_OK = 13,
BTC_DBG_SLOT_B2W = 14,
BTC_DBG_SLOT_W1 = 15,
BTC_DBG_SLOT_W2 = 16,
BTC_DBG_SLOT_W2B = 17,
BTC_DBG_SLOT_B1 = 18,
BTC_DBG_SLOT_B2 = 19,
BTC_DBG_SLOT_B3 = 20,
BTC_DBG_SLOT_B4 = 21,
BTC_DBG_SLOT_LK = 22,
BTC_DBG_SLOT_E2G = 23,
BTC_DBG_SLOT_E5G = 24,
BTC_DBG_SLOT_EBT = 25,
BTC_DBG_SLOT_WLK = 26,
BTC_DBG_SLOT_B1FDD = 27,
BTC_DBG_BT_CHANGE = 28,
BTC_DBG_WL_CCA = 29,
BTC_DBG_BT_LEAUDIO = 30,
BTC_DBG_USER_DEF = 31,
};
void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev);
void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev);
void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode);
@ -193,4 +308,65 @@ static inline u8 rtw89_btc_path_phymap(struct rtw89_dev *rtwdev,
return rtw89_btc_phymap(rtwdev, phy_idx, BIT(path));
}
/* return bt req len in TU */
static inline u16 rtw89_coex_query_bt_req_len(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
struct rtw89_btc *btc = &rtwdev->btc;
return btc->bt_req_len;
}
static inline u32 rtw89_get_antpath_type(u8 phy_map, u8 type)
{
return ((phy_map << 8) + type);
}
static inline
void _slot_set_le(struct rtw89_btc *btc, u8 sid, __le16 dura, __le32 tbl, __le16 type)
{
if (btc->ver->fcxslots == 1) {
btc->dm.slot.v1[sid].dur = dura;
btc->dm.slot.v1[sid].cxtbl = tbl;
btc->dm.slot.v1[sid].cxtype = type;
} else if (btc->ver->fcxslots == 7) {
btc->dm.slot.v7[sid].dur = dura;
btc->dm.slot.v7[sid].cxtype = type;
btc->dm.slot.v7[sid].cxtbl = tbl;
}
}
static inline
void _slot_set(struct rtw89_btc *btc, u8 sid, u16 dura, u32 tbl, u16 type)
{
_slot_set_le(btc, sid, cpu_to_le16(dura), cpu_to_le32(tbl), cpu_to_le16(type));
}
static inline
void _slot_set_dur(struct rtw89_btc *btc, u8 sid, u16 dura)
{
if (btc->ver->fcxslots == 1)
btc->dm.slot.v1[sid].dur = cpu_to_le16(dura);
else if (btc->ver->fcxslots == 7)
btc->dm.slot.v7[sid].dur = cpu_to_le16(dura);
}
static inline
void _slot_set_type(struct rtw89_btc *btc, u8 sid, u16 type)
{
if (btc->ver->fcxslots == 1)
btc->dm.slot.v1[sid].cxtype = cpu_to_le16(type);
else if (btc->ver->fcxslots == 7)
btc->dm.slot.v7[sid].cxtype = cpu_to_le16(type);
}
static inline
void _slot_set_tbl(struct rtw89_btc *btc, u8 sid, u32 tbl)
{
if (btc->ver->fcxslots == 1)
btc->dm.slot.v1[sid].cxtbl = cpu_to_le32(tbl);
else if (btc->ver->fcxslots == 7)
btc->dm.slot.v7[sid].cxtbl = cpu_to_le32(tbl);
}
#endif

1229
core.c

File diff suppressed because it is too large Load Diff

1457
core.h

File diff suppressed because it is too large Load Diff

434
debug.c
View File

@ -367,7 +367,11 @@ static int rtw89_debug_priv_rf_reg_dump_get(struct seq_file *m, void *v)
}
struct txpwr_ent {
const char *txt;
bool nested;
union {
const char *txt;
const struct txpwr_ent *ptr;
};
u8 len;
};
@ -379,6 +383,12 @@ struct txpwr_map {
u32 addr_to_1ss;
};
#define __GEN_TXPWR_ENT_NESTED(_e) \
{ .nested = true, .ptr = __txpwr_ent_##_e, \
.len = ARRAY_SIZE(__txpwr_ent_##_e) }
#define __GEN_TXPWR_ENT0(_t) { .len = 0, .txt = _t }
#define __GEN_TXPWR_ENT2(_t, _e0, _e1) \
{ .len = 2, .txt = _t "\t- " _e0 " " _e1 }
@ -390,7 +400,7 @@ struct txpwr_map {
_e0 " " _e1 " " _e2 " " _e3 " " \
_e4 " " _e5 " " _e6 " " _e7 }
static const struct txpwr_ent __txpwr_ent_byr[] = {
static const struct txpwr_ent __txpwr_ent_byr_ax[] = {
__GEN_TXPWR_ENT4("CCK ", "1M ", "2M ", "5.5M ", "11M "),
__GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
__GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
@ -406,18 +416,18 @@ static const struct txpwr_ent __txpwr_ent_byr[] = {
__GEN_TXPWR_ENT4("HEDCM_2NSS", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
};
static_assert((ARRAY_SIZE(__txpwr_ent_byr) * 4) ==
static_assert((ARRAY_SIZE(__txpwr_ent_byr_ax) * 4) ==
(R_AX_PWR_BY_RATE_MAX - R_AX_PWR_BY_RATE + 4));
static const struct txpwr_map __txpwr_map_byr = {
.ent = __txpwr_ent_byr,
.size = ARRAY_SIZE(__txpwr_ent_byr),
static const struct txpwr_map __txpwr_map_byr_ax = {
.ent = __txpwr_ent_byr_ax,
.size = ARRAY_SIZE(__txpwr_ent_byr_ax),
.addr_from = R_AX_PWR_BY_RATE,
.addr_to = R_AX_PWR_BY_RATE_MAX,
.addr_to_1ss = R_AX_PWR_BY_RATE_1SS_MAX,
};
static const struct txpwr_ent __txpwr_ent_lmt[] = {
static const struct txpwr_ent __txpwr_ent_lmt_ax[] = {
/* 1TX */
__GEN_TXPWR_ENT2("CCK_1TX_20M ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("CCK_1TX_40M ", "NON_BF", "BF"),
@ -462,18 +472,18 @@ static const struct txpwr_ent __txpwr_ent_lmt[] = {
__GEN_TXPWR_ENT2("MCS_2TX_40M_2p5", "NON_BF", "BF"),
};
static_assert((ARRAY_SIZE(__txpwr_ent_lmt) * 2) ==
static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ax) * 2) ==
(R_AX_PWR_LMT_MAX - R_AX_PWR_LMT + 4));
static const struct txpwr_map __txpwr_map_lmt = {
.ent = __txpwr_ent_lmt,
.size = ARRAY_SIZE(__txpwr_ent_lmt),
static const struct txpwr_map __txpwr_map_lmt_ax = {
.ent = __txpwr_ent_lmt_ax,
.size = ARRAY_SIZE(__txpwr_ent_lmt_ax),
.addr_from = R_AX_PWR_LMT,
.addr_to = R_AX_PWR_LMT_MAX,
.addr_to_1ss = R_AX_PWR_LMT_1SS_MAX,
};
static const struct txpwr_ent __txpwr_ent_lmt_ru[] = {
static const struct txpwr_ent __txpwr_ent_lmt_ru_ax[] = {
/* 1TX */
__GEN_TXPWR_ENT8("1TX", "RU26__0", "RU26__1", "RU26__2", "RU26__3",
"RU26__4", "RU26__5", "RU26__6", "RU26__7"),
@ -490,25 +500,207 @@ static const struct txpwr_ent __txpwr_ent_lmt_ru[] = {
"RU106_4", "RU106_5", "RU106_6", "RU106_7"),
};
static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ru) * 8) ==
static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ru_ax) * 8) ==
(R_AX_PWR_RU_LMT_MAX - R_AX_PWR_RU_LMT + 4));
static const struct txpwr_map __txpwr_map_lmt_ru = {
.ent = __txpwr_ent_lmt_ru,
.size = ARRAY_SIZE(__txpwr_ent_lmt_ru),
static const struct txpwr_map __txpwr_map_lmt_ru_ax = {
.ent = __txpwr_ent_lmt_ru_ax,
.size = ARRAY_SIZE(__txpwr_ent_lmt_ru_ax),
.addr_from = R_AX_PWR_RU_LMT,
.addr_to = R_AX_PWR_RU_LMT_MAX,
.addr_to_1ss = R_AX_PWR_RU_LMT_1SS_MAX,
};
static u8 __print_txpwr_ent(struct seq_file *m, const struct txpwr_ent *ent,
const s8 *buf, const u8 cur)
static const struct txpwr_ent __txpwr_ent_byr_mcs_be[] = {
__GEN_TXPWR_ENT4("MCS_1SS ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
__GEN_TXPWR_ENT4("MCS_1SS ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
__GEN_TXPWR_ENT4("MCS_1SS ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
__GEN_TXPWR_ENT2("MCS_1SS ", "MCS12 ", "MCS13 \t"),
__GEN_TXPWR_ENT4("HEDCM_1SS ", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
__GEN_TXPWR_ENT4("DLRU_MCS_1SS ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
__GEN_TXPWR_ENT4("DLRU_MCS_1SS ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
__GEN_TXPWR_ENT4("DLRU_MCS_1SS ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
__GEN_TXPWR_ENT2("DLRU_MCS_1SS ", "MCS12 ", "MCS13 \t"),
__GEN_TXPWR_ENT4("DLRU_HEDCM_1SS", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
__GEN_TXPWR_ENT4("MCS_2SS ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
__GEN_TXPWR_ENT4("MCS_2SS ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
__GEN_TXPWR_ENT4("MCS_2SS ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
__GEN_TXPWR_ENT2("MCS_2SS ", "MCS12 ", "MCS13 \t"),
__GEN_TXPWR_ENT4("HEDCM_2SS ", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
__GEN_TXPWR_ENT4("DLRU_MCS_2SS ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
__GEN_TXPWR_ENT4("DLRU_MCS_2SS ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
__GEN_TXPWR_ENT4("DLRU_MCS_2SS ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
__GEN_TXPWR_ENT2("DLRU_MCS_2SS ", "MCS12 ", "MCS13 \t"),
__GEN_TXPWR_ENT4("DLRU_HEDCM_2SS", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
};
static const struct txpwr_ent __txpwr_ent_byr_be[] = {
__GEN_TXPWR_ENT0("BW20"),
__GEN_TXPWR_ENT4("CCK ", "1M ", "2M ", "5.5M ", "11M "),
__GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
__GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
__GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
__GEN_TXPWR_ENT0("BW40"),
__GEN_TXPWR_ENT4("CCK ", "1M ", "2M ", "5.5M ", "11M "),
__GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
__GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
__GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
/* there is no CCK section after BW80 */
__GEN_TXPWR_ENT0("BW80"),
__GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
__GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
__GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
__GEN_TXPWR_ENT0("BW160"),
__GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
__GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
__GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
__GEN_TXPWR_ENT0("BW320"),
__GEN_TXPWR_ENT4("LEGACY ", "6M ", "9M ", "12M ", "18M "),
__GEN_TXPWR_ENT4("LEGACY ", "24M ", "36M ", "48M ", "54M "),
__GEN_TXPWR_ENT2("EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT2("DLRU_EHT ", "MCS14 ", "MCS15 \t"),
__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
};
static const struct txpwr_map __txpwr_map_byr_be = {
.ent = __txpwr_ent_byr_be,
.size = ARRAY_SIZE(__txpwr_ent_byr_be),
.addr_from = R_BE_PWR_BY_RATE,
.addr_to = R_BE_PWR_BY_RATE_MAX,
.addr_to_1ss = 0, /* not support */
};
static const struct txpwr_ent __txpwr_ent_lmt_mcs_be[] = {
__GEN_TXPWR_ENT2("MCS_20M_0 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_1 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_2 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_3 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_4 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_5 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_6 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_7 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_8 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_9 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_10 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_11 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_12 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_13 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_14 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_20M_15 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_0 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_1 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_2 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_3 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_4 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_5 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_6 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_7 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_80M_0 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_80M_1 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_80M_2 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_80M_3 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_160M_0 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_160M_1 ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_320M ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_0p5", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_2p5", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_4p5", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("MCS_40M_6p5", "NON_BF", "BF"),
};
static const struct txpwr_ent __txpwr_ent_lmt_be[] = {
__GEN_TXPWR_ENT0("1TX"),
__GEN_TXPWR_ENT2("CCK_20M ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("CCK_40M ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("OFDM ", "NON_BF", "BF"),
__GEN_TXPWR_ENT_NESTED(lmt_mcs_be),
__GEN_TXPWR_ENT0("2TX"),
__GEN_TXPWR_ENT2("CCK_20M ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("CCK_40M ", "NON_BF", "BF"),
__GEN_TXPWR_ENT2("OFDM ", "NON_BF", "BF"),
__GEN_TXPWR_ENT_NESTED(lmt_mcs_be),
};
static const struct txpwr_map __txpwr_map_lmt_be = {
.ent = __txpwr_ent_lmt_be,
.size = ARRAY_SIZE(__txpwr_ent_lmt_be),
.addr_from = R_BE_PWR_LMT,
.addr_to = R_BE_PWR_LMT_MAX,
.addr_to_1ss = 0, /* not support */
};
static const struct txpwr_ent __txpwr_ent_lmt_ru_indexes_be[] = {
__GEN_TXPWR_ENT8("RU26 ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
"IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
__GEN_TXPWR_ENT8("RU26 ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
"IDX_12", "IDX_13", "IDX_14", "IDX_15"),
__GEN_TXPWR_ENT8("RU52 ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
"IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
__GEN_TXPWR_ENT8("RU52 ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
"IDX_12", "IDX_13", "IDX_14", "IDX_15"),
__GEN_TXPWR_ENT8("RU106 ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
"IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
__GEN_TXPWR_ENT8("RU106 ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
"IDX_12", "IDX_13", "IDX_14", "IDX_15"),
__GEN_TXPWR_ENT8("RU52_26 ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
"IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
__GEN_TXPWR_ENT8("RU52_26 ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
"IDX_12", "IDX_13", "IDX_14", "IDX_15"),
__GEN_TXPWR_ENT8("RU106_26", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
"IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
__GEN_TXPWR_ENT8("RU106_26", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
"IDX_12", "IDX_13", "IDX_14", "IDX_15"),
};
static const struct txpwr_ent __txpwr_ent_lmt_ru_be[] = {
__GEN_TXPWR_ENT0("1TX"),
__GEN_TXPWR_ENT_NESTED(lmt_ru_indexes_be),
__GEN_TXPWR_ENT0("2TX"),
__GEN_TXPWR_ENT_NESTED(lmt_ru_indexes_be),
};
static const struct txpwr_map __txpwr_map_lmt_ru_be = {
.ent = __txpwr_ent_lmt_ru_be,
.size = ARRAY_SIZE(__txpwr_ent_lmt_ru_be),
.addr_from = R_BE_PWR_RU_LMT,
.addr_to = R_BE_PWR_RU_LMT_MAX,
.addr_to_1ss = 0, /* not support */
};
static unsigned int
__print_txpwr_ent(struct seq_file *m, const struct txpwr_ent *ent,
const s8 *buf, const unsigned int cur)
{
unsigned int cnt, i;
char *fmt;
if (ent->nested) {
for (cnt = 0, i = 0; i < ent->len; i++)
cnt += __print_txpwr_ent(m, ent->ptr + i, buf,
cur + cnt);
return cnt;
}
switch (ent->len) {
case 0:
seq_printf(m, "\t<< %s >>\n", ent->txt);
return 0;
case 2:
fmt = "%s\t| %3d, %3d,\tdBm\n";
fmt = "%s\t| %3d, %3d,\t\tdBm\n";
seq_printf(m, fmt, ent->txt, buf[cur], buf[cur + 1]);
return 2;
case 4:
@ -532,10 +724,10 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
{
u8 fct = rtwdev->chip->txpwr_factor_mac;
u8 path_num = rtwdev->chip->rf_path_num;
unsigned int cur, i;
u32 max_valid_addr;
u32 val, addr;
s8 *buf, tmp;
u8 cur, i;
int ret;
buf = vzalloc(map->addr_to - map->addr_from + 4);
@ -547,6 +739,9 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
else
max_valid_addr = map->addr_to;
if (max_valid_addr == 0)
return -EOPNOTSUPP;
for (addr = map->addr_from; addr <= max_valid_addr; addr += 4) {
ret = rtw89_mac_txpwr_read32(rtwdev, RTW89_PHY_0, addr, &val);
if (ret)
@ -572,9 +767,9 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
seq_puts(m, #_regd "\n"); \
break
static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev)
static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
u8 band = chan->band_type;
u8 regd = rtw89_regd_get(rtwdev, band);
@ -600,33 +795,90 @@ static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev)
#undef case_REGD
struct dbgfs_txpwr_table {
const struct txpwr_map *byr;
const struct txpwr_map *lmt;
const struct txpwr_map *lmt_ru;
};
static const struct dbgfs_txpwr_table dbgfs_txpwr_table_ax = {
.byr = &__txpwr_map_byr_ax,
.lmt = &__txpwr_map_lmt_ax,
.lmt_ru = &__txpwr_map_lmt_ru_ax,
};
static const struct dbgfs_txpwr_table dbgfs_txpwr_table_be = {
.byr = &__txpwr_map_byr_be,
.lmt = &__txpwr_map_lmt_be,
.lmt_ru = &__txpwr_map_lmt_ru_be,
};
static const struct dbgfs_txpwr_table *dbgfs_txpwr_tables[RTW89_CHIP_GEN_NUM] = {
[RTW89_CHIP_AX] = &dbgfs_txpwr_table_ax,
[RTW89_CHIP_BE] = &dbgfs_txpwr_table_be,
};
static
void rtw89_debug_priv_txpwr_table_get_regd(struct seq_file *m,
struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan)
{
const struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_reg_6ghz_tpe *tpe6 = &regulatory->reg_6ghz_tpe;
seq_printf(m, "[Chanctx] band %u, ch %u, bw %u\n",
chan->band_type, chan->channel, chan->band_width);
seq_puts(m, "[Regulatory] ");
__print_regd(m, rtwdev, chan);
if (chan->band_type == RTW89_BAND_6G) {
seq_printf(m, "[reg6_pwr_type] %u\n", regulatory->reg_6ghz_power);
if (tpe6->valid)
seq_printf(m, "[TPE] %d dBm\n", tpe6->constraint);
}
}
static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v)
{
struct rtw89_debugfs_priv *debugfs_priv = m->private;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
const struct dbgfs_txpwr_table *tbl;
const struct rtw89_chan *chan;
int ret = 0;
mutex_lock(&rtwdev->mutex);
rtw89_leave_ps_mode(rtwdev);
chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
seq_puts(m, "[Regulatory] ");
__print_regd(m, rtwdev);
rtw89_debug_priv_txpwr_table_get_regd(m, rtwdev, chan);
seq_puts(m, "[SAR]\n");
rtw89_print_sar(m, rtwdev);
rtw89_print_sar(m, rtwdev, chan->freq);
seq_puts(m, "[TAS]\n");
rtw89_print_tas(m, rtwdev);
tbl = dbgfs_txpwr_tables[chip_gen];
if (!tbl) {
ret = -EOPNOTSUPP;
goto err;
}
seq_puts(m, "\n[TX power byrate]\n");
ret = __print_txpwr_map(m, rtwdev, &__txpwr_map_byr);
ret = __print_txpwr_map(m, rtwdev, tbl->byr);
if (ret)
goto err;
seq_puts(m, "\n[TX power limit]\n");
ret = __print_txpwr_map(m, rtwdev, &__txpwr_map_lmt);
ret = __print_txpwr_map(m, rtwdev, tbl->lmt);
if (ret)
goto err;
seq_puts(m, "\n[TX power limit_ru]\n");
ret = __print_txpwr_map(m, rtwdev, &__txpwr_map_lmt_ru);
ret = __print_txpwr_map(m, rtwdev, tbl->lmt_ru);
if (ret)
goto err;
@ -790,6 +1042,9 @@ static void rtw89_debug_dump_mac_mem(struct seq_file *m,
struct rtw89_dev *rtwdev,
u8 sel, u32 start_addr, u32 len)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 filter_model_addr = mac->filter_model_addr;
u32 indir_access_addr = mac->indir_access_addr;
u32 base_addr, start_page, residue;
u32 i, j, p, pages;
u32 dump_len, remain;
@ -799,17 +1054,17 @@ static void rtw89_debug_dump_mac_mem(struct seq_file *m,
pages = len / MAC_MEM_DUMP_PAGE_SIZE + 1;
start_page = start_addr / MAC_MEM_DUMP_PAGE_SIZE;
residue = start_addr % MAC_MEM_DUMP_PAGE_SIZE;
base_addr = rtw89_mac_mem_base_addrs[sel];
base_addr = mac->mem_base_addrs[sel];
base_addr += start_page * MAC_MEM_DUMP_PAGE_SIZE;
for (p = 0; p < pages; p++) {
dump_len = min_t(u32, remain, MAC_MEM_DUMP_PAGE_SIZE);
rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, base_addr);
for (i = R_AX_INDIR_ACCESS_ENTRY + residue;
i < R_AX_INDIR_ACCESS_ENTRY + dump_len;) {
rtw89_write32(rtwdev, filter_model_addr, base_addr);
for (i = indir_access_addr + residue;
i < indir_access_addr + dump_len;) {
seq_printf(m, "%08xh:", i);
for (j = 0;
j < 4 && i < R_AX_INDIR_ACCESS_ENTRY + dump_len;
j < 4 && i < indir_access_addr + dump_len;
j++, i += 4) {
val = rtw89_read32(rtwdev, i);
seq_printf(m, " %08x", val);
@ -2762,7 +3017,7 @@ static bool is_dbg_port_valid(struct rtw89_dev *rtwdev, u32 sel)
sel >= RTW89_DBG_PORT_SEL_PCIE_TXDMA &&
sel <= RTW89_DBG_PORT_SEL_PCIE_MISC2)
return false;
if (rtwdev->chip->chip_id == RTL8852B &&
if (rtw89_is_rtl885xb(rtwdev) &&
sel >= RTW89_DBG_PORT_SEL_PTCL_C1 &&
sel <= RTW89_DBG_PORT_SEL_TXTF_INFOH_C1)
return false;
@ -3096,13 +3351,14 @@ rtw89_debug_priv_early_h2c_set(struct file *filp, const char __user *user_buf,
static int rtw89_dbg_trigger_ctrl_error(struct rtw89_dev *rtwdev)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct rtw89_cpuio_ctrl ctrl_para = {0};
u16 pkt_id;
int ret;
rtw89_leave_ps_mode(rtwdev);
ret = rtw89_mac_dle_buf_req(rtwdev, 0x20, true, &pkt_id);
ret = mac->dle_buf_req(rtwdev, 0x20, true, &pkt_id);
if (ret)
return ret;
@ -3114,7 +3370,7 @@ static int rtw89_dbg_trigger_ctrl_error(struct rtw89_dev *rtwdev)
ctrl_para.dst_pid = WDE_DLE_PORT_ID_WDRLS;
ctrl_para.dst_qid = WDE_DLE_QUEID_NO_REPORT;
if (rtw89_mac_set_cpuio(rtwdev, &ctrl_para, true))
if (mac->set_cpuio(rtwdev, &ctrl_para, true))
return -EFAULT;
return 0;
@ -3192,14 +3448,17 @@ static ssize_t rtw89_debug_priv_btc_manual_set(struct file *filp,
struct rtw89_debugfs_priv *debugfs_priv = filp->private_data;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
struct rtw89_btc *btc = &rtwdev->btc;
bool btc_manual;
const struct rtw89_btc_ver *ver = btc->ver;
int ret;
ret = kstrtobool_from_user(user_buf, count, &btc_manual);
ret = kstrtobool_from_user(user_buf, count, &btc->manual_ctrl);
if (ret)
return ret;
btc->ctrl.manual = btc_manual;
if (ver->fcxctrl == 7)
btc->ctrl.ctrl_v7.manual = btc->manual_ctrl;
else
btc->ctrl.ctrl.manual = btc->manual_ctrl;
return count;
}
@ -3233,6 +3492,11 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
[NL80211_RATE_INFO_HE_GI_1_6] = "1.6",
[NL80211_RATE_INFO_HE_GI_3_2] = "3.2",
};
static const char * const eht_gi_str[] = {
[NL80211_RATE_INFO_EHT_GI_0_8] = "0.8",
[NL80211_RATE_INFO_EHT_GI_1_6] = "1.6",
[NL80211_RATE_INFO_EHT_GI_3_2] = "3.2",
};
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rate_info *rate = &rtwsta->ra_report.txrate;
struct ieee80211_rx_status *status = &rtwsta->rx_status;
@ -3258,6 +3522,10 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
seq_printf(m, "HE %dSS MCS-%d GI:%s", rate->nss, rate->mcs,
rate->he_gi <= NL80211_RATE_INFO_HE_GI_3_2 ?
he_gi_str[rate->he_gi] : "N/A");
else if (rate->flags & RATE_INFO_FLAGS_EHT_MCS)
seq_printf(m, "EHT %dSS MCS-%d GI:%s", rate->nss, rate->mcs,
rate->eht_gi < ARRAY_SIZE(eht_gi_str) ?
eht_gi_str[rate->eht_gi] : "N/A");
else
seq_printf(m, "Legacy %d", rate->legacy);
seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : "");
@ -3284,7 +3552,12 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
case RX_ENC_HE:
seq_printf(m, "HE %dSS MCS-%d GI:%s", status->nss, status->rate_idx,
status->he_gi <= NL80211_RATE_INFO_HE_GI_3_2 ?
he_gi_str[rate->he_gi] : "N/A");
he_gi_str[status->he_gi] : "N/A");
break;
case RX_ENC_EHT:
seq_printf(m, "EHT %dSS MCS-%d GI:%s", status->nss, status->rate_idx,
status->eht.gi < ARRAY_SIZE(eht_gi_str) ?
eht_gi_str[status->eht.gi] : "N/A");
break;
}
seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(status->bw));
@ -3393,17 +3666,21 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v)
}
static void rtw89_dump_addr_cam(struct seq_file *m,
struct rtw89_dev *rtwdev,
struct rtw89_addr_cam_entry *addr_cam)
{
struct rtw89_sec_cam_entry *sec_entry;
struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
const struct rtw89_sec_cam_entry *sec_entry;
u8 sec_cam_idx;
int i;
seq_printf(m, "\taddr_cam_idx=%u\n", addr_cam->addr_cam_idx);
seq_printf(m, "\t-> bssid_cam_idx=%u\n", addr_cam->bssid_cam_idx);
seq_printf(m, "\tsec_cam_bitmap=%*ph\n", (int)sizeof(addr_cam->sec_cam_map),
addr_cam->sec_cam_map);
for (i = 0; i < RTW89_SEC_CAM_IN_ADDR_CAM; i++) {
sec_entry = addr_cam->sec_entries[i];
for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) {
sec_cam_idx = addr_cam->sec_ent[i];
sec_entry = cam_info->sec_entries[sec_cam_idx];
if (!sec_entry)
continue;
seq_printf(m, "\tsec[%d]: sec_cam_idx %u", i, sec_entry->sec_cam_idx);
@ -3442,12 +3719,13 @@ static
void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct rtw89_dev *rtwdev = rtwvif->rtwdev;
struct seq_file *m = (struct seq_file *)data;
struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
seq_printf(m, "VIF [%d] %pM\n", rtwvif->mac_id, rtwvif->mac_addr);
seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx);
rtw89_dump_addr_cam(m, &rtwvif->addr_cam);
rtw89_dump_addr_cam(m, rtwdev, &rtwvif->addr_cam);
rtw89_dump_pkt_offload(m, &rtwvif->general_pkt_list, "\tpkt_ofld[GENERAL]: ");
}
@ -3474,11 +3752,12 @@ static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta)
static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rtw89_dev *rtwdev = rtwsta->rtwdev;
struct seq_file *m = (struct seq_file *)data;
seq_printf(m, "STA [%d] %pM %s\n", rtwsta->mac_id, sta->addr,
sta->tdls ? "(TDLS)" : "");
rtw89_dump_addr_cam(m, &rtwsta->addr_cam);
rtw89_dump_addr_cam(m, rtwdev, &rtwsta->addr_cam);
rtw89_dump_ba_cam(m, rtwsta);
}
@ -3522,6 +3801,58 @@ static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
return 0;
}
#define DM_INFO(type) {RTW89_DM_ ## type, #type}
static const struct rtw89_disabled_dm_info {
enum rtw89_dm_type type;
const char *name;
} rtw89_disabled_dm_infos[] = {
DM_INFO(DYNAMIC_EDCCA),
};
static int
rtw89_debug_priv_disable_dm_get(struct seq_file *m, void *v)
{
struct rtw89_debugfs_priv *debugfs_priv = m->private;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
const struct rtw89_disabled_dm_info *info;
struct rtw89_hal *hal = &rtwdev->hal;
u32 disabled;
int i;
seq_printf(m, "Disabled DM: 0x%x\n", hal->disabled_dm_bitmap);
for (i = 0; i < ARRAY_SIZE(rtw89_disabled_dm_infos); i++) {
info = &rtw89_disabled_dm_infos[i];
disabled = BIT(info->type) & hal->disabled_dm_bitmap;
seq_printf(m, "[%d] %s: %c\n", info->type, info->name,
disabled ? 'X' : 'O');
}
return 0;
}
static ssize_t
rtw89_debug_priv_disable_dm_set(struct file *filp, const char __user *user_buf,
size_t count, loff_t *loff)
{
struct seq_file *m = (struct seq_file *)filp->private_data;
struct rtw89_debugfs_priv *debugfs_priv = m->private;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
struct rtw89_hal *hal = &rtwdev->hal;
u32 conf;
int ret;
ret = kstrtou32_from_user(user_buf, count, 0, &conf);
if (ret)
return -EINVAL;
hal->disabled_dm_bitmap = conf;
return count;
}
static struct rtw89_debugfs_priv rtw89_debug_priv_read_reg = {
.cb_read = rtw89_debug_priv_read_reg_get,
.cb_write = rtw89_debug_priv_read_reg_select,
@ -3597,6 +3928,11 @@ static struct rtw89_debugfs_priv rtw89_debug_priv_stations = {
.cb_read = rtw89_debug_priv_stations_get,
};
static struct rtw89_debugfs_priv rtw89_debug_priv_disable_dm = {
.cb_read = rtw89_debug_priv_disable_dm_get,
.cb_write = rtw89_debug_priv_disable_dm_set,
};
#define rtw89_debugfs_add(name, mode, fopname, parent) \
do { \
rtw89_debug_priv_ ##name.rtwdev = rtwdev; \
@ -3637,13 +3973,13 @@ void rtw89_debugfs_init(struct rtw89_dev *rtwdev)
rtw89_debugfs_add_w(fw_log_manual);
rtw89_debugfs_add_r(phy_info);
rtw89_debugfs_add_r(stations);
rtw89_debugfs_add_rw(disable_dm);
}
#endif
#ifdef CONFIG_RTW89_DEBUGMSG
void __rtw89_debug(struct rtw89_dev *rtwdev,
enum rtw89_debug_mask mask,
const char *fmt, ...)
void rtw89_debug(struct rtw89_dev *rtwdev, enum rtw89_debug_mask mask,
const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
@ -3659,5 +3995,5 @@ void __rtw89_debug(struct rtw89_dev *rtwdev,
va_end(args);
}
EXPORT_SYMBOL(__rtw89_debug);
EXPORT_SYMBOL(rtw89_debug);
#endif

19
debug.h
View File

@ -29,6 +29,8 @@ enum rtw89_debug_mask {
RTW89_DBG_WOW = BIT(18),
RTW89_DBG_UL_TB = BIT(19),
RTW89_DBG_CHAN = BIT(20),
RTW89_DBG_ACPI = BIT(21),
RTW89_DBG_EDCCA = BIT(22),
RTW89_DBG_UNEXP = BIT(31),
};
@ -57,12 +59,10 @@ static inline void rtw89_debugfs_init(struct rtw89_dev *rtwdev) {}
#ifdef CONFIG_RTW89_DEBUGMSG
extern unsigned int rtw89_debug_mask;
#define rtw89_debug(rtwdev, a...) __rtw89_debug(rtwdev, ##a)
__printf(3, 4)
void __rtw89_debug(struct rtw89_dev *rtwdev,
enum rtw89_debug_mask mask,
const char *fmt, ...);
void rtw89_debug(struct rtw89_dev *rtwdev, enum rtw89_debug_mask mask,
const char *fmt, ...);
static inline void rtw89_hex_dump(struct rtw89_dev *rtwdev,
enum rtw89_debug_mask mask,
const char *prefix_str,
@ -73,6 +73,12 @@ static inline void rtw89_hex_dump(struct rtw89_dev *rtwdev,
print_hex_dump_bytes(prefix_str, DUMP_PREFIX_OFFSET, buf, len);
}
static inline bool rtw89_debug_is_enabled(struct rtw89_dev *rtwdev,
enum rtw89_debug_mask mask)
{
return !!(rtw89_debug_mask & mask);
}
#else
static inline void rtw89_debug(struct rtw89_dev *rtwdev,
enum rtw89_debug_mask mask,
@ -81,6 +87,11 @@ static inline void rtw89_hex_dump(struct rtw89_dev *rtwdev,
enum rtw89_debug_mask mask,
const char *prefix_str,
const void *buf, size_t len) {}
static inline bool rtw89_debug_is_enabled(struct rtw89_dev *rtwdev,
enum rtw89_debug_mask mask)
{
return false;
}
#endif
#endif

11
efuse.c
View File

@ -114,6 +114,11 @@ static int rtw89_dump_physical_efuse_map_ddv(struct rtw89_dev *rtwdev, u8 *map,
return 0;
}
int rtw89_cnv_efuse_state_ax(struct rtw89_dev *rtwdev, bool idle)
{
return 0;
}
static int rtw89_dump_physical_efuse_map_dav(struct rtw89_dev *rtwdev, u8 *map,
u32 dump_addr, u32 dump_size)
{
@ -231,7 +236,7 @@ static int rtw89_dump_logical_efuse_map(struct rtw89_dev *rtwdev, u8 *phy_map,
return 0;
}
int rtw89_parse_efuse_map(struct rtw89_dev *rtwdev)
int rtw89_parse_efuse_map_ax(struct rtw89_dev *rtwdev)
{
u32 phy_size = rtwdev->chip->physical_efuse_size;
u32 log_size = rtwdev->chip->logical_efuse_size;
@ -286,7 +291,7 @@ int rtw89_parse_efuse_map(struct rtw89_dev *rtwdev)
rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "log_map: ", log_map, full_log_size);
ret = rtwdev->chip->ops->read_efuse(rtwdev, log_map);
ret = rtwdev->chip->ops->read_efuse(rtwdev, log_map, RTW89_EFUSE_BLOCK_IGNORE);
if (ret) {
rtw89_warn(rtwdev, "failed to read efuse map\n");
goto out_free;
@ -300,7 +305,7 @@ int rtw89_parse_efuse_map(struct rtw89_dev *rtwdev)
return ret;
}
int rtw89_parse_phycap_map(struct rtw89_dev *rtwdev)
int rtw89_parse_phycap_map_ax(struct rtw89_dev *rtwdev)
{
u32 phycap_addr = rtwdev->chip->phycap_addr;
u32 phycap_size = rtwdev->chip->phycap_size;

18
efuse.h
View File

@ -7,8 +7,22 @@
#include "core.h"
int rtw89_parse_efuse_map(struct rtw89_dev *rtwdev);
int rtw89_parse_phycap_map(struct rtw89_dev *rtwdev);
#define RTW89_EFUSE_BLOCK_ID_MASK GENMASK(31, 16)
#define RTW89_EFUSE_BLOCK_SIZE_MASK GENMASK(15, 0)
#define RTW89_EFUSE_MAX_BLOCK_SIZE 0x10000
struct rtw89_efuse_block_cfg {
u32 offset;
u32 size;
};
int rtw89_parse_efuse_map_ax(struct rtw89_dev *rtwdev);
int rtw89_parse_phycap_map_ax(struct rtw89_dev *rtwdev);
int rtw89_cnv_efuse_state_ax(struct rtw89_dev *rtwdev, bool idle);
int rtw89_parse_efuse_map_be(struct rtw89_dev *rtwdev);
int rtw89_parse_phycap_map_be(struct rtw89_dev *rtwdev);
int rtw89_cnv_efuse_state_be(struct rtw89_dev *rtwdev, bool idle);
int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *efv);
int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev);
#endif

562
efuse_be.c Normal file
View File

@ -0,0 +1,562 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2023 Realtek Corporation
*/
#include "debug.h"
#include "efuse.h"
#include "mac.h"
#include "reg.h"
#define EFUSE_EXTERNALPN_ADDR_BE 0x1580
#define EFUSE_B1_MSSDEVTYPE_MASK GENMASK(3, 0)
#define EFUSE_B1_MSSCUSTIDX0_MASK GENMASK(7, 4)
#define EFUSE_SERIALNUM_ADDR_BE 0x1581
#define EFUSE_B2_MSSKEYNUM_MASK GENMASK(3, 0)
#define EFUSE_B2_MSSCUSTIDX1_MASK BIT(6)
#define EFUSE_SB_CRYP_SEL_ADDR 0x1582
#define EFUSE_SB_CRYP_SEL_SIZE 2
#define EFUSE_SB_CRYP_SEL_DEFAULT 0xFFFF
#define SB_SEL_MGN_MAX_SIZE 2
#define EFUSE_SEC_BE_START 0x1580
#define EFUSE_SEC_BE_SIZE 4
enum rtw89_efuse_mss_dev_type {
MSS_DEV_TYPE_FWSEC_DEF = 0xF,
MSS_DEV_TYPE_FWSEC_WINLIN_INBOX = 0xC,
MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB = 0xA,
MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_COB = 0x9,
MSS_DEV_TYPE_FWSEC_NONWIN_INBOX = 0x6,
};
static const u32 sb_sel_mgn[SB_SEL_MGN_MAX_SIZE] = {
0x8000100, 0xC000180
};
static void rtw89_enable_efuse_pwr_cut_ddv_be(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_hal *hal = &rtwdev->hal;
bool aphy_patch = true;
if (chip->chip_id == RTL8922A && hal->cv == CHIP_CAV)
aphy_patch = false;
rtw89_write8_set(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK);
if (aphy_patch) {
rtw89_write16_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_S);
mdelay(1);
rtw89_write16_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_B);
rtw89_write16_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_ISO_EB2CORE);
}
rtw89_write32_set(rtwdev, R_BE_EFUSE_CTRL_2_V1, B_BE_EF_BURST);
}
static void rtw89_disable_efuse_pwr_cut_ddv_be(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_hal *hal = &rtwdev->hal;
bool aphy_patch = true;
if (chip->chip_id == RTL8922A && hal->cv == CHIP_CAV)
aphy_patch = false;
if (aphy_patch) {
rtw89_write16_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_ISO_EB2CORE);
rtw89_write16_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_B);
mdelay(1);
rtw89_write16_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_S);
}
rtw89_write8_clr(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK);
rtw89_write32_clr(rtwdev, R_BE_EFUSE_CTRL_2_V1, B_BE_EF_BURST);
}
static int rtw89_dump_physical_efuse_map_ddv_be(struct rtw89_dev *rtwdev, u8 *map,
u32 dump_addr, u32 dump_size)
{
u32 efuse_ctl;
u32 addr;
u32 data;
int ret;
if (!IS_ALIGNED(dump_addr, 4) || !IS_ALIGNED(dump_size, 4)) {
rtw89_err(rtwdev, "Efuse addr 0x%x or size 0x%x not aligned\n",
dump_addr, dump_size);
return -EINVAL;
}
rtw89_enable_efuse_pwr_cut_ddv_be(rtwdev);
for (addr = dump_addr; addr < dump_addr + dump_size; addr += 4, map += 4) {
efuse_ctl = u32_encode_bits(addr, B_BE_EF_ADDR_MASK);
rtw89_write32(rtwdev, R_BE_EFUSE_CTRL, efuse_ctl & ~B_BE_EF_RDY);
ret = read_poll_timeout_atomic(rtw89_read32, efuse_ctl,
efuse_ctl & B_BE_EF_RDY, 1, 1000000,
true, rtwdev, R_BE_EFUSE_CTRL);
if (ret)
return -EBUSY;
data = rtw89_read32(rtwdev, R_BE_EFUSE_CTRL_1_V1);
*((__le32 *)map) = cpu_to_le32(data);
}
rtw89_disable_efuse_pwr_cut_ddv_be(rtwdev);
return 0;
}
static int rtw89_dump_physical_efuse_map_dav_be(struct rtw89_dev *rtwdev, u8 *map,
u32 dump_addr, u32 dump_size)
{
u32 addr;
u8 val8;
int err;
int ret;
for (addr = dump_addr; addr < dump_addr + dump_size; addr++) {
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0x40,
FULL_BIT_MASK);
if (ret)
return ret;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_LOW_ADDR, addr & 0xff,
XTAL_SI_LOW_ADDR_MASK);
if (ret)
return ret;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, addr >> 8,
XTAL_SI_HIGH_ADDR_MASK);
if (ret)
return ret;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0,
XTAL_SI_MODE_SEL_MASK);
if (ret)
return ret;
ret = read_poll_timeout_atomic(rtw89_mac_read_xtal_si, err,
!err && (val8 & XTAL_SI_RDY),
1, 10000, false,
rtwdev, XTAL_SI_CTRL, &val8);
if (ret) {
rtw89_warn(rtwdev, "failed to read dav efuse\n");
return ret;
}
ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_READ_VAL, &val8);
if (ret)
return ret;
*map++ = val8;
}
return 0;
}
int rtw89_cnv_efuse_state_be(struct rtw89_dev *rtwdev, bool idle)
{
u32 val;
int ret = 0;
if (idle) {
rtw89_write32_set(rtwdev, R_BE_WL_BT_PWR_CTRL, B_BE_BT_DISN_EN);
} else {
rtw89_write32_clr(rtwdev, R_BE_WL_BT_PWR_CTRL, B_BE_BT_DISN_EN);
ret = read_poll_timeout(rtw89_read32_mask, val,
val == MAC_AX_SYS_ACT, 50, 5000,
false, rtwdev, R_BE_IC_PWR_STATE,
B_BE_WHOLE_SYS_PWR_STE_MASK);
if (ret)
rtw89_warn(rtwdev, "failed to convert efuse state\n");
}
return ret;
}
static int rtw89_dump_physical_efuse_map_be(struct rtw89_dev *rtwdev, u8 *map,
u32 dump_addr, u32 dump_size, bool dav)
{
int ret;
if (!map || dump_size == 0)
return 0;
rtw89_cnv_efuse_state_be(rtwdev, false);
if (dav) {
ret = rtw89_dump_physical_efuse_map_dav_be(rtwdev, map,
dump_addr, dump_size);
if (ret)
return ret;
rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "phy_map dav: ", map, dump_size);
} else {
ret = rtw89_dump_physical_efuse_map_ddv_be(rtwdev, map,
dump_addr, dump_size);
if (ret)
return ret;
rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "phy_map ddv: ", map, dump_size);
}
rtw89_cnv_efuse_state_be(rtwdev, true);
return 0;
}
#define EFUSE_HDR_CONST_MASK GENMASK(23, 20)
#define EFUSE_HDR_PAGE_MASK GENMASK(19, 17)
#define EFUSE_HDR_OFFSET_MASK GENMASK(16, 4)
#define EFUSE_HDR_OFFSET_DAV_MASK GENMASK(11, 4)
#define EFUSE_HDR_WORD_EN_MASK GENMASK(3, 0)
#define invalid_efuse_header_be(hdr1, hdr2, hdr3) \
((hdr1) == 0xff || (hdr2) == 0xff || (hdr3) == 0xff)
#define invalid_efuse_content_be(word_en, i) \
(((word_en) & BIT(i)) != 0x0)
#define get_efuse_blk_idx_be(hdr1, hdr2, hdr3) \
(((hdr1) << 16) | ((hdr2) << 8) | (hdr3))
#define block_idx_to_logical_idx_be(blk_idx, i) \
(((blk_idx) << 3) + ((i) << 1))
#define invalid_efuse_header_dav_be(hdr1, hdr2) \
((hdr1) == 0xff || (hdr2) == 0xff)
#define get_efuse_blk_idx_dav_be(hdr1, hdr2) \
(((hdr1) << 8) | (hdr2))
static int rtw89_eeprom_parser_be(struct rtw89_dev *rtwdev,
const u8 *phy_map, u32 phy_size, u8 *log_map,
const struct rtw89_efuse_block_cfg *efuse_block)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
enum rtw89_efuse_block blk_page, page;
u32 size = efuse_block->size;
u32 phy_idx, log_idx;
u32 hdr, page_offset;
u8 hdr1, hdr2, hdr3;
u8 i, val0, val1;
u32 min, max;
u16 blk_idx;
u8 word_en;
page = u32_get_bits(efuse_block->offset, RTW89_EFUSE_BLOCK_ID_MASK);
page_offset = u32_get_bits(efuse_block->offset, RTW89_EFUSE_BLOCK_SIZE_MASK);
min = ALIGN_DOWN(page_offset, 2);
max = ALIGN(page_offset + size, 2);
memset(log_map, 0xff, size);
phy_idx = chip->sec_ctrl_efuse_size;
do {
if (page == RTW89_EFUSE_BLOCK_ADIE) {
hdr1 = phy_map[phy_idx];
hdr2 = phy_map[phy_idx + 1];
if (invalid_efuse_header_dav_be(hdr1, hdr2))
break;
phy_idx += 2;
hdr = get_efuse_blk_idx_dav_be(hdr1, hdr2);
blk_page = RTW89_EFUSE_BLOCK_ADIE;
blk_idx = u32_get_bits(hdr, EFUSE_HDR_OFFSET_DAV_MASK);
word_en = u32_get_bits(hdr, EFUSE_HDR_WORD_EN_MASK);
} else {
hdr1 = phy_map[phy_idx];
hdr2 = phy_map[phy_idx + 1];
hdr3 = phy_map[phy_idx + 2];
if (invalid_efuse_header_be(hdr1, hdr2, hdr3))
break;
phy_idx += 3;
hdr = get_efuse_blk_idx_be(hdr1, hdr2, hdr3);
blk_page = u32_get_bits(hdr, EFUSE_HDR_PAGE_MASK);
blk_idx = u32_get_bits(hdr, EFUSE_HDR_OFFSET_MASK);
word_en = u32_get_bits(hdr, EFUSE_HDR_WORD_EN_MASK);
}
if (blk_idx >= RTW89_EFUSE_MAX_BLOCK_SIZE >> 3) {
rtw89_err(rtwdev, "[ERR]efuse idx:0x%X\n", phy_idx - 3);
rtw89_err(rtwdev, "[ERR]read hdr:0x%X\n", hdr);
return -EINVAL;
}
for (i = 0; i < 4; i++) {
if (invalid_efuse_content_be(word_en, i))
continue;
if (phy_idx >= phy_size - 1)
return -EINVAL;
log_idx = block_idx_to_logical_idx_be(blk_idx, i);
if (blk_page == page && log_idx >= min && log_idx < max) {
val0 = phy_map[phy_idx];
val1 = phy_map[phy_idx + 1];
if (log_idx == min && page_offset > min) {
log_map[log_idx - page_offset + 1] = val1;
} else if (log_idx + 2 == max &&
page_offset + size < max) {
log_map[log_idx - page_offset] = val0;
} else {
log_map[log_idx - page_offset] = val0;
log_map[log_idx - page_offset + 1] = val1;
}
}
phy_idx += 2;
}
} while (phy_idx < phy_size);
return 0;
}
static int rtw89_parse_logical_efuse_block_be(struct rtw89_dev *rtwdev,
const u8 *phy_map, u32 phy_size,
enum rtw89_efuse_block block)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_efuse_block_cfg *efuse_block;
u8 *log_map;
int ret;
efuse_block = &chip->efuse_blocks[block];
log_map = kmalloc(efuse_block->size, GFP_KERNEL);
if (!log_map)
return -ENOMEM;
ret = rtw89_eeprom_parser_be(rtwdev, phy_map, phy_size, log_map, efuse_block);
if (ret) {
rtw89_warn(rtwdev, "failed to dump efuse logical block %d\n", block);
goto out_free;
}
rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "log_map: ", log_map, efuse_block->size);
ret = rtwdev->chip->ops->read_efuse(rtwdev, log_map, block);
if (ret) {
rtw89_warn(rtwdev, "failed to read efuse map\n");
goto out_free;
}
out_free:
kfree(log_map);
return ret;
}
int rtw89_parse_efuse_map_be(struct rtw89_dev *rtwdev)
{
u32 phy_size = rtwdev->chip->physical_efuse_size;
u32 dav_phy_size = rtwdev->chip->dav_phy_efuse_size;
enum rtw89_efuse_block block;
u8 *phy_map = NULL;
u8 *dav_phy_map = NULL;
int ret;
if (rtw89_read16(rtwdev, R_BE_SYS_WL_EFUSE_CTRL) & B_BE_AUTOLOAD_SUS)
rtwdev->efuse.valid = true;
else
rtw89_warn(rtwdev, "failed to check efuse autoload\n");
phy_map = kmalloc(phy_size, GFP_KERNEL);
if (dav_phy_size)
dav_phy_map = kmalloc(dav_phy_size, GFP_KERNEL);
if (!phy_map || (dav_phy_size && !dav_phy_map)) {
ret = -ENOMEM;
goto out_free;
}
ret = rtw89_dump_physical_efuse_map_be(rtwdev, phy_map, 0, phy_size, false);
if (ret) {
rtw89_warn(rtwdev, "failed to dump efuse physical map\n");
goto out_free;
}
ret = rtw89_dump_physical_efuse_map_be(rtwdev, dav_phy_map, 0, dav_phy_size, true);
if (ret) {
rtw89_warn(rtwdev, "failed to dump efuse dav physical map\n");
goto out_free;
}
if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
block = RTW89_EFUSE_BLOCK_HCI_DIG_USB;
else
block = RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO;
ret = rtw89_parse_logical_efuse_block_be(rtwdev, phy_map, phy_size, block);
if (ret) {
rtw89_warn(rtwdev, "failed to parse efuse logic block %d\n",
RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO);
goto out_free;
}
ret = rtw89_parse_logical_efuse_block_be(rtwdev, phy_map, phy_size,
RTW89_EFUSE_BLOCK_RF);
if (ret) {
rtw89_warn(rtwdev, "failed to parse efuse logic block %d\n",
RTW89_EFUSE_BLOCK_RF);
goto out_free;
}
out_free:
kfree(dav_phy_map);
kfree(phy_map);
return ret;
}
int rtw89_parse_phycap_map_be(struct rtw89_dev *rtwdev)
{
u32 phycap_addr = rtwdev->chip->phycap_addr;
u32 phycap_size = rtwdev->chip->phycap_size;
u8 *phycap_map = NULL;
int ret = 0;
if (!phycap_size)
return 0;
phycap_map = kmalloc(phycap_size, GFP_KERNEL);
if (!phycap_map)
return -ENOMEM;
ret = rtw89_dump_physical_efuse_map_be(rtwdev, phycap_map,
phycap_addr, phycap_size, false);
if (ret) {
rtw89_warn(rtwdev, "failed to dump phycap map\n");
goto out_free;
}
ret = rtwdev->chip->ops->read_phycap(rtwdev, phycap_map);
if (ret) {
rtw89_warn(rtwdev, "failed to read phycap map\n");
goto out_free;
}
out_free:
kfree(phycap_map);
return ret;
}
static u16 get_sb_cryp_sel_idx(u16 sb_cryp_sel)
{
u8 low_bit, high_bit, cnt_zero = 0;
u8 idx, sel_form_v, sel_idx_v;
u16 sb_cryp_sel_v = 0x0;
sel_form_v = u16_get_bits(sb_cryp_sel, MASKBYTE0);
sel_idx_v = u16_get_bits(sb_cryp_sel, MASKBYTE1);
for (idx = 0; idx < 4; idx++) {
low_bit = !!(sel_form_v & BIT(idx));
high_bit = !!(sel_form_v & BIT(7 - idx));
if (low_bit != high_bit)
return U16_MAX;
if (low_bit)
continue;
cnt_zero++;
if (cnt_zero == 1)
sb_cryp_sel_v = idx * 16;
else if (cnt_zero > 1)
return U16_MAX;
}
low_bit = u8_get_bits(sel_idx_v, 0x0F);
high_bit = u8_get_bits(sel_idx_v, 0xF0);
if ((low_bit ^ high_bit) != 0xF)
return U16_MAX;
return sb_cryp_sel_v + low_bit;
}
static u8 get_mss_dev_type_idx(struct rtw89_dev *rtwdev, u8 mss_dev_type)
{
switch (mss_dev_type) {
case MSS_DEV_TYPE_FWSEC_WINLIN_INBOX:
mss_dev_type = 0x0;
break;
case MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB:
mss_dev_type = 0x1;
break;
case MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_COB:
mss_dev_type = 0x2;
break;
case MSS_DEV_TYPE_FWSEC_NONWIN_INBOX:
mss_dev_type = 0x3;
break;
case MSS_DEV_TYPE_FWSEC_DEF:
mss_dev_type = RTW89_FW_MSS_DEV_TYPE_FWSEC_DEF;
break;
default:
rtw89_warn(rtwdev, "unknown mss_dev_type %d", mss_dev_type);
mss_dev_type = RTW89_FW_MSS_DEV_TYPE_FWSEC_INV;
break;
}
return mss_dev_type;
}
int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev)
{
struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
u32 sec_addr = EFUSE_SEC_BE_START;
u32 sec_size = EFUSE_SEC_BE_SIZE;
u16 sb_cryp_sel, sb_cryp_sel_idx;
u8 sec_map[EFUSE_SEC_BE_SIZE];
u8 mss_dev_type;
u8 b1, b2;
int ret;
ret = rtw89_dump_physical_efuse_map_be(rtwdev, sec_map,
sec_addr, sec_size, false);
if (ret) {
rtw89_warn(rtwdev, "failed to dump secsel map\n");
return ret;
}
sb_cryp_sel = sec_map[EFUSE_SB_CRYP_SEL_ADDR - sec_addr] |
sec_map[EFUSE_SB_CRYP_SEL_ADDR - sec_addr + 1] << 8;
if (sb_cryp_sel == EFUSE_SB_CRYP_SEL_DEFAULT)
goto out;
sb_cryp_sel_idx = get_sb_cryp_sel_idx(sb_cryp_sel);
if (sb_cryp_sel_idx >= SB_SEL_MGN_MAX_SIZE) {
rtw89_warn(rtwdev, "invalid SB cryp sel idx %d\n", sb_cryp_sel_idx);
goto out;
}
sec->sb_sel_mgn = sb_sel_mgn[sb_cryp_sel_idx];
b1 = sec_map[EFUSE_EXTERNALPN_ADDR_BE - sec_addr];
b2 = sec_map[EFUSE_SERIALNUM_ADDR_BE - sec_addr];
mss_dev_type = u8_get_bits(b1, EFUSE_B1_MSSDEVTYPE_MASK);
sec->mss_cust_idx = 0x1F - (u8_get_bits(b1, EFUSE_B1_MSSCUSTIDX0_MASK) |
u8_get_bits(b2, EFUSE_B2_MSSCUSTIDX1_MASK) << 4);
sec->mss_key_num = 0xF - u8_get_bits(b2, EFUSE_B2_MSSKEYNUM_MASK);
sec->mss_dev_type = get_mss_dev_type_idx(rtwdev, mss_dev_type);
if (sec->mss_dev_type == RTW89_FW_MSS_DEV_TYPE_FWSEC_INV) {
rtw89_warn(rtwdev, "invalid mss_dev_type %d\n", mss_dev_type);
goto out;
}
sec->secure_boot = true;
out:
rtw89_debug(rtwdev, RTW89_DBG_FW,
"MSS secure_boot=%d dev_type=%d cust_idx=%d key_num=%d\n",
sec->secure_boot, sec->mss_dev_type, sec->mss_cust_idx,
sec->mss_key_num);
return 0;
}
EXPORT_SYMBOL(rtw89_efuse_read_fw_secure_be);

3908
fw.c

File diff suppressed because it is too large Load Diff

2313
fw.h

File diff suppressed because it is too large Load Diff

1728
mac.c

File diff suppressed because it is too large Load Diff

377
mac.h
View File

@ -10,6 +10,7 @@
#define MAC_MEM_DUMP_PAGE_SIZE 0x40000
#define ADDR_CAM_ENT_SIZE 0x40
#define ADDR_CAM_ENT_SHORT_SIZE 0x20
#define BSSID_CAM_ENT_SIZE 0x08
#define HFC_PAGE_UNIT 64
#define RPWM_TRY_CNT 3
@ -168,6 +169,12 @@ enum rtw89_mac_ax_l0_to_l1_event {
MAC_AX_L0_TO_L1_EVENT_MAX = 15,
};
enum rtw89_mac_wow_fw_status {
WOWLAN_NOT_READY = 0x00,
WOWLAN_SLEEP_READY = 0x01,
WOWLAN_RESUME_READY = 0x02,
};
#define RTW89_PORT_OFFSET_TU_TO_32US(shift_tu) ((shift_tu) * 1024 / 32)
enum rtw89_mac_dbg_port_sel {
@ -275,6 +282,7 @@ enum rtw89_mac_dbg_port_sel {
/* SRAM mem dump */
#define R_AX_INDIR_ACCESS_ENTRY 0x40000
#define R_BE_INDIR_ACCESS_ENTRY 0x80000
#define AXIDMA_BASE_ADDR 0x18006000
#define STA_SCHED_BASE_ADDR 0x18808000
@ -298,6 +306,31 @@ enum rtw89_mac_dbg_port_sel {
#define TXDATA_FIFO_1_BASE_ADDR 0x188A1000
#define CPU_LOCAL_BASE_ADDR 0x18003000
#define WD_PAGE_BASE_ADDR_BE 0x0
#define CPU_LOCAL_BASE_ADDR_BE 0x18003000
#define AXIDMA_BASE_ADDR_BE 0x18006000
#define SHARED_BUF_BASE_ADDR_BE 0x18700000
#define DMAC_TBL_BASE_ADDR_BE 0x18800000
#define SHCUT_MACHDR_BASE_ADDR_BE 0x18800800
#define STA_SCHED_BASE_ADDR_BE 0x18818000
#define NAT25_CAM_BASE_ADDR_BE 0x18820000
#define RXPLD_FLTR_CAM_BASE_ADDR_BE 0x18823000
#define SEC_CAM_BASE_ADDR_BE 0x18824000
#define WOW_CAM_BASE_ADDR_BE 0x18828000
#define MLD_TBL_BASE_ADDR_BE 0x18829000
#define RX_CLSF_CAM_BASE_ADDR_BE 0x1882A000
#define CMAC_TBL_BASE_ADDR_BE 0x18840000
#define ADDR_CAM_BASE_ADDR_BE 0x18850000
#define BSSID_CAM_BASE_ADDR_BE 0x18858000
#define BA_CAM_BASE_ADDR_BE 0x18859000
#define BCN_IE_CAM0_BASE_ADDR_BE 0x18860000
#define TXDATA_FIFO_0_BASE_ADDR_BE 0x18861000
#define TXD_FIFO_0_BASE_ADDR_BE 0x18862000
#define BCN_IE_CAM1_BASE_ADDR_BE 0x18880000
#define TXDATA_FIFO_1_BASE_ADDR_BE 0x18881000
#define TXD_FIFO_1_BASE_ADDR_BE 0x18881800
#define DCPU_LOCAL_BASE_ADDR_BE 0x19C02000
#define CCTL_INFO_SIZE 32
enum rtw89_mac_mem_sel {
@ -322,13 +355,12 @@ enum rtw89_mac_mem_sel {
RTW89_MAC_MEM_BSSID_CAM,
RTW89_MAC_MEM_TXD_FIFO_0_V1,
RTW89_MAC_MEM_TXD_FIFO_1_V1,
RTW89_MAC_MEM_WD_PAGE,
/* keep last */
RTW89_MAC_MEM_NUM,
};
extern const u32 rtw89_mac_mem_base_addrs[];
enum rtw89_rpwm_req_pwr_state {
RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE = 0,
RTW89_MAC_RPWM_REQ_PWR_STATE_BAND0_RFON = 1,
@ -380,13 +412,28 @@ enum rtw89_mac_c2h_mcc_func {
NUM_OF_RTW89_MAC_C2H_FUNC_MCC,
};
enum rtw89_mac_c2h_mrc_func {
RTW89_MAC_C2H_FUNC_MRC_TSF_RPT = 0,
RTW89_MAC_C2H_FUNC_MRC_STATUS_RPT = 1,
NUM_OF_RTW89_MAC_C2H_FUNC_MRC,
};
enum rtw89_mac_c2h_wow_func {
RTW89_MAC_C2H_FUNC_AOAC_REPORT,
RTW89_MAC_C2H_FUNC_READ_WOW_CAM,
NUM_OF_RTW89_MAC_C2H_FUNC_WOW,
};
enum rtw89_mac_c2h_class {
RTW89_MAC_C2H_CLASS_INFO,
RTW89_MAC_C2H_CLASS_OFLD,
RTW89_MAC_C2H_CLASS_TWT,
RTW89_MAC_C2H_CLASS_WOW,
RTW89_MAC_C2H_CLASS_MCC,
RTW89_MAC_C2H_CLASS_FWDBG,
RTW89_MAC_C2H_CLASS_INFO = 0x0,
RTW89_MAC_C2H_CLASS_OFLD = 0x1,
RTW89_MAC_C2H_CLASS_TWT = 0x2,
RTW89_MAC_C2H_CLASS_WOW = 0x3,
RTW89_MAC_C2H_CLASS_MCC = 0x4,
RTW89_MAC_C2H_CLASS_FWDBG = 0x5,
RTW89_MAC_C2H_CLASS_MRC = 0xe,
RTW89_MAC_C2H_CLASS_MAX,
};
@ -415,6 +462,22 @@ enum rtw89_mac_mcc_status {
RTW89_MAC_MCC_TXNULL1_FAIL = 27,
};
enum rtw89_mac_mrc_status {
RTW89_MAC_MRC_START_SCH_OK = 0,
RTW89_MAC_MRC_STOP_SCH_OK = 1,
RTW89_MAC_MRC_DEL_SCH_OK = 2,
RTW89_MAC_MRC_EMPTY_SCH_FAIL = 16,
RTW89_MAC_MRC_ROLE_NOT_EXIST_FAIL = 17,
RTW89_MAC_MRC_DATA_NOT_FOUND_FAIL = 18,
RTW89_MAC_MRC_GET_NEXT_SLOT_FAIL = 19,
RTW89_MAC_MRC_ALT_ROLE_FAIL = 20,
RTW89_MAC_MRC_ADD_PSTIMER_FAIL = 21,
RTW89_MAC_MRC_MALLOC_FAIL = 22,
RTW89_MAC_MRC_SWITCH_CH_FAIL = 23,
RTW89_MAC_MRC_TXNULL0_FAIL = 24,
RTW89_MAC_MRC_PORT_FUNC_EN_FAIL = 25,
};
struct rtw89_mac_ax_coex {
#define RTW89_MAC_AX_COEX_RTK_MODE 0
#define RTW89_MAC_AX_COEX_CSR_MODE 1
@ -478,6 +541,7 @@ enum rtw89_mac_bf_rrsc_rate {
({typeof(_addr) __addr = (_addr); \
__addr >= R_AX_CMAC_REG_START && __addr <= R_AX_CMAC_REG_END; })
#define RTW89_MAC_AX_BAND_REG_OFFSET 0x2000
#define RTW89_MAC_BE_BAND_REG_OFFSET 0x4000
#define PTCL_IDLE_POLL_CNT 10000
#define SW_CVR_DUR_US 8
@ -510,6 +574,9 @@ enum rtw89_mac_bf_rrsc_rate {
#define B_CMAC1_MGQ_NO_PWRSAV BIT(11)
#define B_CMAC1_CPUMGQ BIT(12)
#define B_CMAC0_MGQ_NORMAL_BE BIT(2)
#define B_CMAC1_MGQ_NORMAL_BE BIT(30)
#define QEMP_ACQ_GRP_MACID_NUM 8
#define QEMP_ACQ_GRP_QSEL_SH 4
#define QEMP_ACQ_GRP_QSEL_MASK 0xF
@ -623,6 +690,22 @@ struct rtw89_mac_dle_dfi_qempty {
u32 qempty;
};
enum rtw89_mac_dle_rsvd_qt_type {
DLE_RSVD_QT_MPDU_INFO,
DLE_RSVD_QT_B0_CSI,
DLE_RSVD_QT_B1_CSI,
DLE_RSVD_QT_B0_LMR,
DLE_RSVD_QT_B1_LMR,
DLE_RSVD_QT_B0_FTM,
DLE_RSVD_QT_B1_FTM,
};
struct rtw89_mac_dle_rsvd_qt_cfg {
u16 pktid;
u16 pg_num;
u32 size;
};
enum rtw89_mac_error_scenario {
RTW89_RXI300_ERROR = 1,
RTW89_WCPU_CPU_EXCEPTION = 2,
@ -791,27 +874,37 @@ enum mac_ax_err_info {
struct rtw89_mac_size_set {
const struct rtw89_hfc_prec_cfg hfc_preccfg_pcie;
const struct rtw89_hfc_prec_cfg hfc_prec_cfg_c0;
const struct rtw89_hfc_prec_cfg hfc_prec_cfg_c2;
const struct rtw89_dle_size wde_size0;
const struct rtw89_dle_size wde_size0_v1;
const struct rtw89_dle_size wde_size4;
const struct rtw89_dle_size wde_size4_v1;
const struct rtw89_dle_size wde_size6;
const struct rtw89_dle_size wde_size7;
const struct rtw89_dle_size wde_size9;
const struct rtw89_dle_size wde_size18;
const struct rtw89_dle_size wde_size19;
const struct rtw89_dle_size ple_size0;
const struct rtw89_dle_size ple_size0_v1;
const struct rtw89_dle_size ple_size3_v1;
const struct rtw89_dle_size ple_size4;
const struct rtw89_dle_size ple_size6;
const struct rtw89_dle_size ple_size8;
const struct rtw89_dle_size ple_size18;
const struct rtw89_dle_size ple_size19;
const struct rtw89_wde_quota wde_qt0;
const struct rtw89_wde_quota wde_qt0_v1;
const struct rtw89_wde_quota wde_qt4;
const struct rtw89_wde_quota wde_qt6;
const struct rtw89_wde_quota wde_qt7;
const struct rtw89_wde_quota wde_qt17;
const struct rtw89_wde_quota wde_qt18;
const struct rtw89_ple_quota ple_qt0;
const struct rtw89_ple_quota ple_qt1;
const struct rtw89_ple_quota ple_qt4;
const struct rtw89_ple_quota ple_qt5;
const struct rtw89_ple_quota ple_qt9;
const struct rtw89_ple_quota ple_qt13;
const struct rtw89_ple_quota ple_qt18;
const struct rtw89_ple_quota ple_qt44;
@ -822,18 +915,113 @@ struct rtw89_mac_size_set {
const struct rtw89_ple_quota ple_qt_52a_wow;
const struct rtw89_ple_quota ple_qt_52b_wow;
const struct rtw89_ple_quota ple_qt_51b_wow;
const struct rtw89_rsvd_quota ple_rsvd_qt0;
const struct rtw89_rsvd_quota ple_rsvd_qt1;
const struct rtw89_dle_rsvd_size rsvd0_size0;
const struct rtw89_dle_rsvd_size rsvd1_size0;
};
extern const struct rtw89_mac_size_set rtw89_mac_size;
static inline u32 rtw89_mac_reg_by_idx(u32 reg_base, u8 band)
struct rtw89_mac_gen_def {
u32 band1_offset;
u32 filter_model_addr;
u32 indir_access_addr;
const u32 *mem_base_addrs;
u32 rx_fltr;
const struct rtw89_port_reg *port_base;
u32 agg_len_ht;
u32 ps_status;
struct rtw89_reg_def muedca_ctrl;
struct rtw89_reg_def bfee_ctrl;
struct rtw89_reg_def narrow_bw_ru_dis;
struct rtw89_reg_def wow_ctrl;
int (*check_mac_en)(struct rtw89_dev *rtwdev, u8 band,
enum rtw89_mac_hwmod_sel sel);
int (*sys_init)(struct rtw89_dev *rtwdev);
int (*trx_init)(struct rtw89_dev *rtwdev);
void (*hci_func_en)(struct rtw89_dev *rtwdev);
void (*dmac_func_pre_en)(struct rtw89_dev *rtwdev);
void (*dle_func_en)(struct rtw89_dev *rtwdev, bool enable);
void (*dle_clk_en)(struct rtw89_dev *rtwdev, bool enable);
void (*bf_assoc)(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int (*typ_fltr_opt)(struct rtw89_dev *rtwdev,
enum rtw89_machdr_frame_type type,
enum rtw89_mac_fwd_target fwd_target,
u8 mac_idx);
int (*cfg_ppdu_status)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable);
int (*dle_mix_cfg)(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg);
int (*chk_dle_rdy)(struct rtw89_dev *rtwdev, bool wde_or_ple);
int (*dle_buf_req)(struct rtw89_dev *rtwdev, u16 buf_len, bool wd, u16 *pkt_id);
void (*hfc_func_en)(struct rtw89_dev *rtwdev, bool en, bool h2c_en);
void (*hfc_h2c_cfg)(struct rtw89_dev *rtwdev);
void (*hfc_mix_cfg)(struct rtw89_dev *rtwdev);
void (*hfc_get_mix_info)(struct rtw89_dev *rtwdev);
void (*wde_quota_cfg)(struct rtw89_dev *rtwdev,
const struct rtw89_wde_quota *min_cfg,
const struct rtw89_wde_quota *max_cfg,
u16 ext_wde_min_qt_wcpu);
void (*ple_quota_cfg)(struct rtw89_dev *rtwdev,
const struct rtw89_ple_quota *min_cfg,
const struct rtw89_ple_quota *max_cfg);
int (*set_cpuio)(struct rtw89_dev *rtwdev,
struct rtw89_cpuio_ctrl *ctrl_para, bool wd);
int (*dle_quota_change)(struct rtw89_dev *rtwdev, bool band1_en);
void (*disable_cpu)(struct rtw89_dev *rtwdev);
int (*fwdl_enable_wcpu)(struct rtw89_dev *rtwdev, u8 boot_reason,
bool dlfw, bool include_bb);
u8 (*fwdl_get_status)(struct rtw89_dev *rtwdev, enum rtw89_fwdl_check_type type);
int (*fwdl_check_path_ready)(struct rtw89_dev *rtwdev, bool h2c_or_fwdl);
int (*parse_efuse_map)(struct rtw89_dev *rtwdev);
int (*parse_phycap_map)(struct rtw89_dev *rtwdev);
int (*cnv_efuse_state)(struct rtw89_dev *rtwdev, bool idle);
int (*cfg_plt)(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt);
u16 (*get_plt_cnt)(struct rtw89_dev *rtwdev, u8 band);
bool (*get_txpwr_cr)(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
u32 reg_base, u32 *cr);
int (*write_xtal_si)(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 mask);
int (*read_xtal_si)(struct rtw89_dev *rtwdev, u8 offset, u8 *val);
void (*dump_qta_lost)(struct rtw89_dev *rtwdev);
void (*dump_err_status)(struct rtw89_dev *rtwdev,
enum mac_ax_err_info err);
bool (*is_txq_empty)(struct rtw89_dev *rtwdev);
int (*add_chan_list)(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif, bool connected);
int (*scan_offload)(struct rtw89_dev *rtwdev,
struct rtw89_scan_option *option,
struct rtw89_vif *rtwvif);
int (*wow_config_mac)(struct rtw89_dev *rtwdev, bool enable_wow);
};
extern const struct rtw89_mac_gen_def rtw89_mac_gen_ax;
extern const struct rtw89_mac_gen_def rtw89_mac_gen_be;
static inline
u32 rtw89_mac_reg_by_idx(struct rtw89_dev *rtwdev, u32 reg_base, u8 band)
{
return band == 0 ? reg_base : (reg_base + 0x2000);
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
return band == 0 ? reg_base : (reg_base + mac->band1_offset);
}
static inline u32 rtw89_mac_reg_by_port(u32 base, u8 port, u8 mac_idx)
static inline
u32 rtw89_mac_reg_by_port(struct rtw89_dev *rtwdev, u32 base, u8 port, u8 mac_idx)
{
return rtw89_mac_reg_by_idx(base + port * 0x40, mac_idx);
return rtw89_mac_reg_by_idx(rtwdev, base + port * 0x40, mac_idx);
}
static inline u32
@ -841,7 +1029,7 @@ rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base)
{
u32 reg;
reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx);
reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
return rtw89_read32(rtwdev, reg);
}
@ -851,7 +1039,7 @@ rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
{
u32 reg;
reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx);
reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
return rtw89_read32_mask(rtwdev, reg, mask);
}
@ -861,7 +1049,7 @@ rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base,
{
u32 reg;
reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx);
reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
rtw89_write32(rtwdev, reg, data);
}
@ -871,7 +1059,7 @@ rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
{
u32 reg;
reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx);
reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
rtw89_write32_mask(rtwdev, reg, mask, data);
}
@ -881,7 +1069,7 @@ rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
{
u32 reg;
reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx);
reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
rtw89_write16_mask(rtwdev, reg, mask, data);
}
@ -891,7 +1079,7 @@ rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
{
u32 reg;
reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx);
reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
rtw89_write32_clr(rtwdev, reg, bit);
}
@ -901,7 +1089,7 @@ rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
{
u32 reg;
reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx);
reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
rtw89_write16_clr(rtwdev, reg, bit);
}
@ -911,17 +1099,38 @@ rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
{
u32 reg;
reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx);
reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
rtw89_write32_set(rtwdev, reg, bit);
}
void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev);
int rtw89_mac_partial_init(struct rtw89_dev *rtwdev);
int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb);
int rtw89_mac_init(struct rtw89_dev *rtwdev);
int rtw89_mac_dle_init(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode,
enum rtw89_qta_mode ext_mode);
int rtw89_mac_hfc_init(struct rtw89_dev *rtwdev, bool reset, bool en, bool h2c_en);
int rtw89_mac_preload_init(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx,
enum rtw89_qta_mode mode);
bool rtw89_mac_is_qta_dbcc(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode);
static inline
int rtw89_mac_check_mac_en(struct rtw89_dev *rtwdev, u8 band,
enum rtw89_mac_hwmod_sel sel);
enum rtw89_mac_hwmod_sel sel)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
return mac->check_mac_en(rtwdev, band, sel);
}
int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val);
int rtw89_mac_read_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 *val);
int rtw89_mac_dle_dfi_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_dfi_ctrl *ctrl);
int rtw89_mac_dle_dfi_quota_cfg(struct rtw89_dev *rtwdev,
struct rtw89_mac_dle_dfi_quota *quota);
void rtw89_mac_dump_dmac_err_status(struct rtw89_dev *rtwdev);
int rtw89_mac_dle_dfi_qempty_cfg(struct rtw89_dev *rtwdev,
struct rtw89_mac_dle_dfi_qempty *qempty);
void rtw89_mac_dump_l0_to_l1(struct rtw89_dev *rtwdev,
enum mac_ax_err_info err);
int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev,
@ -930,12 +1139,13 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev,
u16 offset_tu);
int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
u64 *tsf);
void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif, bool en);
void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif);
void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en);
int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
void rtw89_mac_disable_cpu(struct rtw89_dev *rtwdev);
int rtw89_mac_enable_cpu(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw);
int rtw89_mac_enable_bb_rf(struct rtw89_dev *rtwdev);
int rtw89_mac_disable_bb_rf(struct rtw89_dev *rtwdev);
@ -953,9 +1163,27 @@ static inline int rtw89_chip_disable_bb_rf(struct rtw89_dev *rtwdev)
return chip->ops->disable_bb_rf(rtwdev);
}
static inline int rtw89_chip_reset_bb_rf(struct rtw89_dev *rtwdev)
{
int ret;
if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
return 0;
ret = rtw89_chip_disable_bb_rf(rtwdev);
if (ret)
return ret;
ret = rtw89_chip_enable_bb_rf(rtwdev);
if (ret)
return ret;
return 0;
}
u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev);
int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err);
bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func);
bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
u8 class, u8 func);
void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
u32 len, u8 class, u8 func);
int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev);
@ -963,9 +1191,20 @@ int rtw89_mac_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx,
u32 *tx_en, enum rtw89_sch_tx_sel sel);
int rtw89_mac_stop_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx,
u32 *tx_en, enum rtw89_sch_tx_sel sel);
int rtw89_mac_stop_sch_tx_v2(struct rtw89_dev *rtwdev, u8 mac_idx,
u32 *tx_en, enum rtw89_sch_tx_sel sel);
int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
int rtw89_mac_resume_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_ids, bool enable);
int rtw89_mac_resume_sch_tx_v2(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
static inline
int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
return mac->cfg_ppdu_status(rtwdev, mac_idx, enable);
}
void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx);
void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop);
int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex *coex);
@ -975,20 +1214,44 @@ int rtw89_mac_cfg_gnt(struct rtw89_dev *rtwdev,
const struct rtw89_mac_ax_coex_gnt *gnt_cfg);
int rtw89_mac_cfg_gnt_v1(struct rtw89_dev *rtwdev,
const struct rtw89_mac_ax_coex_gnt *gnt_cfg);
int rtw89_mac_cfg_plt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt);
u16 rtw89_mac_get_plt_cnt(struct rtw89_dev *rtwdev, u8 band);
int rtw89_mac_cfg_gnt_v2(struct rtw89_dev *rtwdev,
const struct rtw89_mac_ax_coex_gnt *gnt_cfg);
static inline
int rtw89_mac_cfg_plt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
return mac->cfg_plt(rtwdev, plt);
}
static inline
u16 rtw89_mac_get_plt_cnt(struct rtw89_dev *rtwdev, u8 band)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
return mac->get_plt_cnt(rtwdev, band);
}
void rtw89_mac_cfg_sb(struct rtw89_dev *rtwdev, u32 val);
u32 rtw89_mac_get_sb(struct rtw89_dev *rtwdev);
bool rtw89_mac_get_ctrl_path(struct rtw89_dev *rtwdev);
int rtw89_mac_cfg_ctrl_path(struct rtw89_dev *rtwdev, bool wl);
int rtw89_mac_cfg_ctrl_path_v1(struct rtw89_dev *rtwdev, bool wl);
bool rtw89_mac_get_txpwr_cr(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
u32 reg_base, u32 *cr);
int rtw89_mac_cfg_ctrl_path_v2(struct rtw89_dev *rtwdev, bool wl);
void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter);
void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev);
static inline
void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
struct ieee80211_sta *sta)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
if (mac->bf_assoc)
mac->bf_assoc(rtwdev, vif, sta);
}
void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
@ -996,6 +1259,7 @@ void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *
void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev,
struct ieee80211_sta *sta, bool disconnect);
void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev);
void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en);
int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev,
@ -1004,6 +1268,9 @@ int rtw89_mac_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause);
static inline void rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev)
{
if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
return;
if (!test_bit(RTW89_FLAG_BFEE_MON, rtwdev->flags))
return;
@ -1014,9 +1281,10 @@ static inline int rtw89_mac_txpwr_read32(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
u32 reg_base, u32 *val)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 cr;
if (!rtw89_mac_get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
if (!mac->get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
return -EINVAL;
*val = rtw89_read32(rtwdev, cr);
@ -1027,9 +1295,10 @@ static inline int rtw89_mac_txpwr_write32(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
u32 reg_base, u32 val)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 cr;
if (!rtw89_mac_get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
if (!mac->get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
return -EINVAL;
rtw89_write32(rtwdev, cr, val);
@ -1040,9 +1309,10 @@ static inline int rtw89_mac_txpwr_write32_mask(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
u32 reg_base, u32 mask, u32 val)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 cr;
if (!rtw89_mac_get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
if (!mac->get_txpwr_cr(rtwdev, phy_idx, reg_base, &cr))
return -EINVAL;
rtw89_write32_mask(rtwdev, cr, mask, val);
@ -1115,15 +1385,19 @@ enum rtw89_mac_xtal_si_offset {
#define XTAL_SC_XI_MASK GENMASK(7, 0)
XTAL_SI_XTAL_SC_XO = 0x05,
#define XTAL_SC_XO_MASK GENMASK(7, 0)
XTAL_SI_XREF_MODE = 0x0B,
XTAL_SI_PWR_CUT = 0x10,
#define XTAL_SI_SMALL_PWR_CUT BIT(0)
#define XTAL_SI_BIG_PWR_CUT BIT(1)
XTAL_SI_XTAL_DRV = 0x15,
#define XTAL_SI_DRV_LATCH BIT(4)
XTAL_SI_XTAL_PLL = 0x16,
XTAL_SI_XTAL_XMD_2 = 0x24,
#define XTAL_SI_LDO_LPS GENMASK(6, 4)
XTAL_SI_XTAL_XMD_4 = 0x26,
#define XTAL_SI_LPS_CAP GENMASK(3, 0)
XTAL_SI_XREF_RF1 = 0x2D,
XTAL_SI_XREF_RF2 = 0x2E,
XTAL_SI_CV = 0x41,
#define XTAL_SI_ACV_MASK GENMASK(3, 0)
XTAL_SI_LOW_ADDR = 0x62,
@ -1151,20 +1425,37 @@ enum rtw89_mac_xtal_si_offset {
XTAL_SI_SRAM_CTRL = 0xA1,
#define XTAL_SI_SRAM_DIS BIT(1)
#define FULL_BIT_MASK GENMASK(7, 0)
XTAL_SI_APBT = 0xD1,
XTAL_SI_PLL = 0xE0,
XTAL_SI_PLL_1 = 0xE1,
};
int rtw89_mac_write_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 mask);
int rtw89_mac_read_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 *val);
static inline
int rtw89_mac_write_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 mask)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
return mac->write_xtal_si(rtwdev, offset, val, mask);
}
static inline
int rtw89_mac_read_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 *val)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
return mac->read_xtal_si(rtwdev, offset, val);
}
void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
int rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd, u16 *pkt_id);
int rtw89_mac_set_cpuio(struct rtw89_dev *rtwdev,
struct rtw89_cpuio_ctrl *ctrl_para, bool wd);
int rtw89_mac_typ_fltr_opt(struct rtw89_dev *rtwdev,
enum rtw89_machdr_frame_type type,
enum rtw89_mac_fwd_target fwd_target, u8 mac_idx);
int rtw89_mac_resize_ple_rx_quota(struct rtw89_dev *rtwdev, bool wow);
int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_mac_idx band);
void rtw89_mac_hw_mgnt_sec(struct rtw89_dev *rtwdev, bool wow);
int rtw89_mac_dle_quota_change(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode,
bool band1_en);
int rtw89_mac_get_dle_rsvd_qt_cfg(struct rtw89_dev *rtwdev,
enum rtw89_mac_dle_rsvd_qt_type type,
struct rtw89_mac_dle_rsvd_qt_cfg *cfg);
int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable);
#endif

View File

@ -66,7 +66,7 @@ static int rtw89_ops_start(struct ieee80211_hw *hw)
return ret;
}
static void rtw89_ops_stop(struct ieee80211_hw *hw)
static void rtw89_ops_stop(struct ieee80211_hw *hw, bool suspend)
{
struct rtw89_dev *rtwdev = hw->priv;
@ -145,6 +145,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
rtwvif->mac_idx = RTW89_MAC_0;
rtwvif->phy_idx = RTW89_PHY_0;
rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
rtwvif->chanctx_assigned = false;
rtwvif->hit_rule = 0;
rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
ether_addr_copy(rtwvif->mac_addr, vif->addr);
@ -224,6 +225,8 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw,
u64 multicast)
{
struct rtw89_dev *rtwdev = hw->priv;
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 rx_fltr;
mutex_lock(&rtwdev->mutex);
rtw89_leave_ps_mode(rtwdev);
@ -270,16 +273,29 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw,
}
}
rx_fltr = rtwdev->hal.rx_fltr;
/* mac80211 doesn't configure filter when HW scan, driver need to
* set by itself. However, during P2P scan might have configure
* filter to overwrite filter that HW scan needed, so we need to
* check scan and append related filter
*/
if (rtwdev->scanning) {
rx_fltr &= ~B_AX_A_BCN_CHK_EN;
rx_fltr &= ~B_AX_A_BC;
rx_fltr &= ~B_AX_A_A1_MATCH;
}
rtw89_write32_mask(rtwdev,
rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0),
rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
B_AX_RX_FLTR_CFG_MASK,
rtwdev->hal.rx_fltr);
rx_fltr);
if (!rtwdev->dbcc_en)
goto out;
rtw89_write32_mask(rtwdev,
rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_1),
rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_1),
B_AX_RX_FLTR_CFG_MASK,
rtwdev->hal.rx_fltr);
rx_fltr);
out:
mutex_unlock(&rtwdev->mutex);
@ -296,12 +312,13 @@ static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif, u8 aifsn)
{
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
rtwvif->sub_entity_idx);
u8 slot_time;
u8 sifs;
slot_time = vif->bss_conf.use_short_slot ? 9 : 20;
sifs = chan->band_type == RTW89_BAND_5G ? 16 : 10;
sifs = chan->band_type == RTW89_BAND_2G ? 10 : 16;
return aifsn * slot_time + sifs;
}
@ -325,11 +342,14 @@ static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev,
rtw89_fw_h2c_set_edca(rtwdev, rtwvif, ac_to_fw_idx[ac], val);
}
static const u32 ac_to_mu_edca_param[IEEE80211_NUM_ACS] = {
[IEEE80211_AC_VO] = R_AX_MUEDCA_VO_PARAM_0,
[IEEE80211_AC_VI] = R_AX_MUEDCA_VI_PARAM_0,
[IEEE80211_AC_BE] = R_AX_MUEDCA_BE_PARAM_0,
[IEEE80211_AC_BK] = R_AX_MUEDCA_BK_PARAM_0,
#define R_MUEDCA_ACS_PARAM(acs) {R_AX_MUEDCA_ ## acs ## _PARAM_0, \
R_BE_MUEDCA_ ## acs ## _PARAM_0}
static const u32 ac_to_mu_edca_param[IEEE80211_NUM_ACS][RTW89_CHIP_GEN_NUM] = {
[IEEE80211_AC_VO] = R_MUEDCA_ACS_PARAM(VO),
[IEEE80211_AC_VI] = R_MUEDCA_ACS_PARAM(VI),
[IEEE80211_AC_BE] = R_MUEDCA_ACS_PARAM(BE),
[IEEE80211_AC_BK] = R_MUEDCA_ACS_PARAM(BK),
};
static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev,
@ -337,6 +357,7 @@ static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev,
{
struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac];
struct ieee80211_he_mu_edca_param_ac_rec *mu_edca;
int gen = rtwdev->chip->chip_gen;
u8 aifs, aifsn;
u16 timer_32us;
u32 reg;
@ -353,7 +374,7 @@ static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev,
val = FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_TIMER_MASK, timer_32us) |
FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_CW_MASK, mu_edca->ecw_min_max) |
FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_AIFS_MASK, aifs);
reg = rtw89_mac_reg_by_idx(ac_to_mu_edca_param[ac], rtwvif->mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen], rtwvif->mac_idx);
rtw89_write32(rtwdev, reg, val);
rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif, true);
@ -376,15 +397,14 @@ static void rtw89_conf_tx(struct rtw89_dev *rtwdev,
}
static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf)
struct ieee80211_vif *vif)
{
struct ieee80211_sta *sta;
if (vif->type != NL80211_IFTYPE_STATION)
return;
sta = ieee80211_find_sta(vif, conf->bssid);
sta = ieee80211_find_sta(vif, vif->cfg.ap_addr);
if (!sta) {
rtw89_err(rtwdev, "can't find sta to set sta_assoc state\n");
return;
@ -395,10 +415,8 @@ static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev,
rtw89_core_sta_assoc(rtwdev, vif, sta);
}
static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf,
u64 changed)
static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u64 changed)
{
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
@ -408,28 +426,51 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ASSOC) {
if (vif->cfg.assoc) {
rtw89_station_mode_sta_assoc(rtwdev, vif, conf);
rtw89_station_mode_sta_assoc(rtwdev, vif);
rtw89_phy_set_bss_color(rtwdev, vif);
rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif);
rtw89_mac_port_update(rtwdev, rtwvif);
rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, vif);
rtw89_queue_chanctx_work(rtwdev);
} else {
/* Abort ongoing scan if cancel_scan isn't issued
* when disconnected by peer
*/
if (rtwdev->scanning)
rtw89_hw_scan_abort(rtwdev, vif);
rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
}
}
if (changed & BSS_CHANGED_PS)
rtw89_recalc_lps(rtwdev);
if (changed & BSS_CHANGED_ARP_FILTER)
rtwvif->ip_addr = vif->cfg.arp_addr_list[0];
mutex_unlock(&rtwdev->mutex);
}
static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf,
u64 changed)
{
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
mutex_lock(&rtwdev->mutex);
rtw89_leave_ps_mode(rtwdev);
if (changed & BSS_CHANGED_BSSID) {
ether_addr_copy(rtwvif->bssid, conf->bssid);
rtw89_cam_bssid_changed(rtwdev, rtwvif);
rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
WRITE_ONCE(rtwvif->sync_bcn_tsf, 0);
}
if (changed & BSS_CHANGED_BEACON)
rtw89_fw_h2c_update_beacon(rtwdev, rtwvif);
rtw89_chip_h2c_update_beacon(rtwdev, rtwvif);
if (changed & BSS_CHANGED_ERP_SLOT)
rtw89_conf_tx(rtwdev, rtwvif);
@ -441,13 +482,13 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw89_mac_bf_set_gid_table(rtwdev, vif, conf);
if (changed & BSS_CHANGED_P2P_PS)
rtw89_process_p2p_ps(rtwdev, vif);
rtw89_core_update_p2p_ps(rtwdev, vif);
if (changed & BSS_CHANGED_CQM)
rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
if (changed & BSS_CHANGED_PS)
rtw89_recalc_lps(rtwdev);
if (changed & BSS_CHANGED_TPE)
rtw89_reg_6ghz_recalc(rtwdev, rtwvif, true);
mutex_unlock(&rtwdev->mutex);
}
@ -468,14 +509,19 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
return -EOPNOTSUPP;
}
if (rtwdev->scanning)
rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid);
rtw89_cam_bssid_changed(rtwdev, rtwvif);
rtw89_mac_port_update(rtwdev, rtwvif);
rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_TYPE_CHANGE);
rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
rtw89_chip_rfk_channel(rtwdev);
rtw89_queue_chanctx_work(rtwdev);
mutex_unlock(&rtwdev->mutex);
return 0;
@ -490,7 +536,7 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_lock(&rtwdev->mutex);
rtw89_mac_stop_ap(rtwdev, rtwvif);
rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
mutex_unlock(&rtwdev->mutex);
}
@ -632,6 +678,8 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
mutex_lock(&rtwdev->mutex);
clear_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags);
clear_bit(tid, rtwsta->ampdu_map);
rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta);
mutex_unlock(&rtwdev->mutex);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
@ -640,17 +688,19 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
set_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags);
rtwsta->ampdu_params[tid].agg_num = params->buf_size;
rtwsta->ampdu_params[tid].amsdu = params->amsdu;
set_bit(tid, rtwsta->ampdu_map);
rtw89_leave_ps_mode(rtwdev);
rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta);
mutex_unlock(&rtwdev->mutex);
break;
case IEEE80211_AMPDU_RX_START:
mutex_lock(&rtwdev->mutex);
rtw89_fw_h2c_ba_cam(rtwdev, rtwsta, true, params);
rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, true, params);
mutex_unlock(&rtwdev->mutex);
break;
case IEEE80211_AMPDU_RX_STOP:
mutex_lock(&rtwdev->mutex);
rtw89_fw_h2c_ba_cam(rtwdev, rtwsta, false, params);
rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, false, params);
mutex_unlock(&rtwdev->mutex);
break;
default:
@ -962,7 +1012,7 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw,
}
if (rtwdev->scanning)
rtw89_hw_scan_abort(rtwdev, vif);
rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
if (type == IEEE80211_ROC_TYPE_MGMT_TX)
roc->state = RTW89_ROC_MGMT;
@ -1073,6 +1123,28 @@ static void rtw89_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled)
device_set_wakeup_enable(rtwdev->dev, enabled);
}
static void rtw89_set_rekey_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *data)
{
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_gtk_info *gtk_info = &rtw_wow->gtk_info;
if (data->kek_len > sizeof(gtk_info->kek) ||
data->kck_len > sizeof(gtk_info->kck)) {
rtw89_warn(rtwdev, "kek or kck length over fw limit\n");
return;
}
mutex_lock(&rtwdev->mutex);
memcpy(gtk_info->kek, data->kek, data->kek_len);
memcpy(gtk_info->kck, data->kck, data->kck_len);
mutex_unlock(&rtwdev->mutex);
}
#endif
const struct ieee80211_ops rtw89_ops = {
@ -1085,7 +1157,8 @@ const struct ieee80211_ops rtw89_ops = {
.change_interface = rtw89_ops_change_interface,
.remove_interface = rtw89_ops_remove_interface,
.configure_filter = rtw89_ops_configure_filter,
.bss_info_changed = rtw89_ops_bss_info_changed,
.vif_cfg_changed = rtw89_ops_vif_cfg_changed,
.link_info_changed = rtw89_ops_link_info_changed,
.start_ap = rtw89_ops_start_ap,
.stop_ap = rtw89_ops_stop_ap,
.set_tim = rtw89_ops_set_tim,
@ -1118,6 +1191,7 @@ const struct ieee80211_ops rtw89_ops = {
.suspend = rtw89_ops_suspend,
.resume = rtw89_ops_resume,
.set_wakeup = rtw89_ops_set_wakeup,
.set_rekey_data = rtw89_set_rekey_data,
#endif
};
EXPORT_SYMBOL(rtw89_ops);

2606
mac_be.c Normal file

File diff suppressed because it is too large Load Diff

794
pci.c

File diff suppressed because it is too large Load Diff

623
pci.h
View File

@ -12,11 +12,18 @@
#define MDIO_PG0_G2 2
#define MDIO_PG1_G2 3
#define RAC_CTRL_PPR 0x00
#define RAC_ANA03 0x03
#define OOBS_SEN_MASK GENMASK(5, 1)
#define RAC_ANA09 0x09
#define BAC_OOBS_SEL BIT(4)
#define RAC_ANA0A 0x0A
#define B_BAC_EQ_SEL BIT(5)
#define RAC_ANA0C 0x0C
#define B_PCIE_BIT_PSAVE BIT(15)
#define RAC_ANA0D 0x0D
#define BAC_RX_TEST_EN BIT(6)
#define RAC_ANA10 0x10
#define ADDR_SEL_PINOUT_DIS_VAL 0x3C4
#define B_PCIE_BIT_PINOUT_DIS BIT(3)
#define RAC_REG_REV2 0x1B
#define BAC_CMU_EN_DLY_MASK GENMASK(15, 12)
@ -26,11 +33,17 @@
#define RAC_REG_FLD_0 0x1D
#define BAC_AUTOK_N_MASK GENMASK(3, 2)
#define PCIE_AUTOK_4 0x3
#define RAC_ANA1E 0x1E
#define RAC_ANA1E_G1_VAL 0x66EA
#define RAC_ANA1E_G2_VAL 0x6EEA
#define RAC_ANA1F 0x1F
#define OOBS_LEVEL_MASK GENMASK(12, 8)
#define RAC_ANA24 0x24
#define B_AX_DEGLITCH GENMASK(11, 8)
#define RAC_ANA26 0x26
#define B_AX_RXEN GENMASK(15, 14)
#define RAC_ANA2E 0x2E
#define RAC_ANA2E_VAL 0xFFFE
#define RAC_CTRL_PPR_V1 0x30
#define B_AX_CLK_CALIB_EN BIT(12)
#define B_AX_CALIB_EN BIT(13)
@ -42,6 +55,7 @@
#define B_AX_DBI_WFLAG BIT(16)
#define B_AX_DBI_WREN_MSK GENMASK(15, 12)
#define B_AX_DBI_ADDR_MSK GENMASK(11, 2)
#define B_AX_DBI_2LSB GENMASK(1, 0)
#define R_AX_DBI_WDATA 0x1094
#define R_AX_DBI_RDATA 0x1098
@ -245,6 +259,220 @@
#define B_AX_HS1ISR_IND_INT BIT(25)
#define B_AX_PCIE_DBG_STE_INT BIT(13)
#define R_BE_PCIE_FRZ_CLK 0x3004
#define B_BE_PCIE_FRZ_MAC_HW_RST BIT(31)
#define B_BE_PCIE_FRZ_CFG_SPC_RST BIT(30)
#define B_BE_PCIE_FRZ_ELBI_RST BIT(29)
#define B_BE_PCIE_MAC_IS_ACTIVE BIT(28)
#define B_BE_PCIE_FRZ_RTK_HW_RST BIT(27)
#define B_BE_PCIE_FRZ_REG_RST BIT(26)
#define B_BE_PCIE_FRZ_ANA_RST BIT(25)
#define B_BE_PCIE_FRZ_WLAN_RST BIT(24)
#define B_BE_PCIE_FRZ_FLR_RST BIT(23)
#define B_BE_PCIE_FRZ_RET_NON_STKY_RST BIT(22)
#define B_BE_PCIE_FRZ_RET_STKY_RST BIT(21)
#define B_BE_PCIE_FRZ_NON_STKY_RST BIT(20)
#define B_BE_PCIE_FRZ_STKY_RST BIT(19)
#define B_BE_PCIE_FRZ_RET_CORE_RST BIT(18)
#define B_BE_PCIE_FRZ_PWR_RST BIT(17)
#define B_BE_PCIE_FRZ_PERST_RST BIT(16)
#define B_BE_PCIE_FRZ_PHY_ALOAD BIT(15)
#define B_BE_PCIE_FRZ_PHY_HW_RST BIT(14)
#define B_BE_PCIE_DBG_CLK BIT(4)
#define B_BE_PCIE_EN_CLK BIT(3)
#define B_BE_PCIE_DBI_ACLK_ACT BIT(2)
#define B_BE_PCIE_S1_ACLK_ACT BIT(1)
#define B_BE_PCIE_EN_AUX_CLK BIT(0)
#define R_BE_PCIE_PS_CTRL 0x3008
#define B_BE_RSM_L0S_EN BIT(8)
#define B_BE_CMAC_EXIT_L1_EN BIT(7)
#define B_BE_DMAC0_EXIT_L1_EN BIT(6)
#define B_BE_FORCE_L0 BIT(5)
#define B_BE_DBI_RO_WR_DISABLE BIT(4)
#define B_BE_SEL_XFER_PENDING BIT(3)
#define B_BE_SEL_REQ_ENTR_L1 BIT(2)
#define B_BE_PCIE_EN_SWENT_L23 BIT(1)
#define B_BE_SEL_REQ_EXIT_L1 BIT(0)
#define R_BE_PCIE_MIX_CFG 0x300C
#define B_BE_L1SS_TIMEOUT_CTRL BIT(18)
#define B_BE_ASPM_CTRL_L1 BIT(17)
#define B_BE_ASPM_CTRL_L0 BIT(16)
#define B_BE_XFER_PENDING_FW BIT(11)
#define B_BE_XFER_PENDING BIT(10)
#define B_BE_REQ_EXIT_L1 BIT(9)
#define B_BE_REQ_ENTR_L1 BIT(8)
#define B_BE_L1SUB_ENABLE BIT(0)
#define R_BE_L1_CLK_CTRL 0x3010
#define B_BE_RAS_SD_HOLD_LTSSM BIT(12)
#define B_BE_CLK_REQ_N BIT(1)
#define B_BE_CLK_PM_EN BIT(0)
#define R_BE_PCIE_LAT_CTRL 0x3044
#define B_BE_ELBI_PHY_REMAP_MASK GENMASK(29, 24)
#define B_BE_SYS_SUS_L12_EN BIT(17)
#define B_BE_MDIO_S_EN BIT(16)
#define B_BE_SYM_AUX_CLK_SEL BIT(15)
#define B_BE_RTK_LDO_POWER_LATENCY_MASK GENMASK(11, 10)
#define B_BE_RTK_LDO_BIAS_LATENCY_MASK GENMASK(9, 8)
#define B_BE_CLK_REQ_LAT_MASK GENMASK(7, 4)
#define B_BE_RTK_PM_SEL_OPT BIT(1)
#define B_BE_CLK_REQ_SEL BIT(0)
#define R_BE_PCIE_HIMR0 0x30B0
#define B_BE_PCIE_HB1_IND_INTA_IMR BIT(31)
#define B_BE_PCIE_HB0_IND_INTA_IMR BIT(30)
#define B_BE_HCI_AXIDMA_INTA_IMR BIT(29)
#define B_BE_HC0_IND_INTA_IMR BIT(28)
#define B_BE_HD1_IND_INTA_IMR BIT(27)
#define B_BE_HD0_IND_INTA_IMR BIT(26)
#define B_BE_HS1_IND_INTA_IMR BIT(25)
#define B_BE_HS0_IND_INTA_IMR BIT(24)
#define B_BE_PCIE_HOTRST_INT_EN BIT(16)
#define B_BE_PCIE_FLR_INT_EN BIT(15)
#define B_BE_PCIE_PERST_INT_EN BIT(14)
#define B_BE_PCIE_DBG_STE_INT_EN BIT(13)
#define B_BE_HB1_IND_INT_EN0 BIT(9)
#define B_BE_HB0_IND_INT_EN0 BIT(8)
#define B_BE_HC1_IND_INT_EN0 BIT(7)
#define B_BE_HCI_AXIDMA_INT_EN0 BIT(5)
#define B_BE_HC0_IND_INT_EN0 BIT(4)
#define B_BE_HD1_IND_INT_EN0 BIT(3)
#define B_BE_HD0_IND_INT_EN0 BIT(2)
#define B_BE_HS1_IND_INT_EN0 BIT(1)
#define B_BE_HS0_IND_INT_EN0 BIT(0)
#define R_BE_PCIE_HISR 0x30B4
#define B_BE_PCIE_HOTRST_INT BIT(16)
#define B_BE_PCIE_FLR_INT BIT(15)
#define B_BE_PCIE_PERST_INT BIT(14)
#define B_BE_PCIE_DBG_STE_INT BIT(13)
#define B_BE_HB1IMR_IND BIT(9)
#define B_BE_HB0IMR_IND BIT(8)
#define B_BE_HC1ISR_IND_INT BIT(7)
#define B_BE_HCI_AXIDMA_INT BIT(5)
#define B_BE_HC0ISR_IND_INT BIT(4)
#define B_BE_HD1ISR_IND_INT BIT(3)
#define B_BE_HD0ISR_IND_INT BIT(2)
#define B_BE_HS1ISR_IND_INT BIT(1)
#define B_BE_HS0ISR_IND_INT BIT(0)
#define R_BE_PCIE_DMA_IMR_0_V1 0x30B8
#define B_BE_PCIE_RX_RX1P1_IMR0_V1 BIT(23)
#define B_BE_PCIE_RX_RX0P1_IMR0_V1 BIT(22)
#define B_BE_PCIE_RX_ROQ1_IMR0_V1 BIT(21)
#define B_BE_PCIE_RX_RPQ1_IMR0_V1 BIT(20)
#define B_BE_PCIE_RX_RX1P2_IMR0_V1 BIT(19)
#define B_BE_PCIE_RX_ROQ0_IMR0_V1 BIT(18)
#define B_BE_PCIE_RX_RPQ0_IMR0_V1 BIT(17)
#define B_BE_PCIE_RX_RX0P2_IMR0_V1 BIT(16)
#define B_BE_PCIE_TX_CH14_IMR0 BIT(14)
#define B_BE_PCIE_TX_CH13_IMR0 BIT(13)
#define B_BE_PCIE_TX_CH12_IMR0 BIT(12)
#define B_BE_PCIE_TX_CH11_IMR0 BIT(11)
#define B_BE_PCIE_TX_CH10_IMR0 BIT(10)
#define B_BE_PCIE_TX_CH9_IMR0 BIT(9)
#define B_BE_PCIE_TX_CH8_IMR0 BIT(8)
#define B_BE_PCIE_TX_CH7_IMR0 BIT(7)
#define B_BE_PCIE_TX_CH6_IMR0 BIT(6)
#define B_BE_PCIE_TX_CH5_IMR0 BIT(5)
#define B_BE_PCIE_TX_CH4_IMR0 BIT(4)
#define B_BE_PCIE_TX_CH3_IMR0 BIT(3)
#define B_BE_PCIE_TX_CH2_IMR0 BIT(2)
#define B_BE_PCIE_TX_CH1_IMR0 BIT(1)
#define B_BE_PCIE_TX_CH0_IMR0 BIT(0)
#define R_BE_PCIE_DMA_ISR 0x30BC
#define B_BE_PCIE_RX_RX1P1_ISR_V1 BIT(23)
#define B_BE_PCIE_RX_RX0P1_ISR_V1 BIT(22)
#define B_BE_PCIE_RX_ROQ1_ISR_V1 BIT(21)
#define B_BE_PCIE_RX_RPQ1_ISR_V1 BIT(20)
#define B_BE_PCIE_RX_RX1P2_ISR_V1 BIT(19)
#define B_BE_PCIE_RX_ROQ0_ISR_V1 BIT(18)
#define B_BE_PCIE_RX_RPQ0_ISR_V1 BIT(17)
#define B_BE_PCIE_RX_RX0P2_ISR_V1 BIT(16)
#define B_BE_PCIE_TX_CH14_ISR BIT(14)
#define B_BE_PCIE_TX_CH13_ISR BIT(13)
#define B_BE_PCIE_TX_CH12_ISR BIT(12)
#define B_BE_PCIE_TX_CH11_ISR BIT(11)
#define B_BE_PCIE_TX_CH10_ISR BIT(10)
#define B_BE_PCIE_TX_CH9_ISR BIT(9)
#define B_BE_PCIE_TX_CH8_ISR BIT(8)
#define B_BE_PCIE_TX_CH7_ISR BIT(7)
#define B_BE_PCIE_TX_CH6_ISR BIT(6)
#define B_BE_PCIE_TX_CH5_ISR BIT(5)
#define B_BE_PCIE_TX_CH4_ISR BIT(4)
#define B_BE_PCIE_TX_CH3_ISR BIT(3)
#define B_BE_PCIE_TX_CH2_ISR BIT(2)
#define B_BE_PCIE_TX_CH1_ISR BIT(1)
#define B_BE_PCIE_TX_CH0_ISR BIT(0)
#define R_BE_HAXI_HIMR00 0xB0B0
#define B_BE_RDU_CH5_INT_IMR_V1 BIT(30)
#define B_BE_RDU_CH4_INT_IMR_V1 BIT(29)
#define B_BE_RDU_CH3_INT_IMR_V1 BIT(28)
#define B_BE_RDU_CH2_INT_IMR_V1 BIT(27)
#define B_BE_RDU_CH1_INT_IMR_V1 BIT(26)
#define B_BE_RDU_CH0_INT_IMR_V1 BIT(25)
#define B_BE_RXDMA_STUCK_INT_EN_V1 BIT(24)
#define B_BE_TXDMA_STUCK_INT_EN_V1 BIT(23)
#define B_BE_TXDMA_CH14_INT_EN_V1 BIT(22)
#define B_BE_TXDMA_CH13_INT_EN_V1 BIT(21)
#define B_BE_TXDMA_CH12_INT_EN_V1 BIT(20)
#define B_BE_TXDMA_CH11_INT_EN_V1 BIT(19)
#define B_BE_TXDMA_CH10_INT_EN_V1 BIT(18)
#define B_BE_TXDMA_CH9_INT_EN_V1 BIT(17)
#define B_BE_TXDMA_CH8_INT_EN_V1 BIT(16)
#define B_BE_TXDMA_CH7_INT_EN_V1 BIT(15)
#define B_BE_TXDMA_CH6_INT_EN_V1 BIT(14)
#define B_BE_TXDMA_CH5_INT_EN_V1 BIT(13)
#define B_BE_TXDMA_CH4_INT_EN_V1 BIT(12)
#define B_BE_TXDMA_CH3_INT_EN_V1 BIT(11)
#define B_BE_TXDMA_CH2_INT_EN_V1 BIT(10)
#define B_BE_TXDMA_CH1_INT_EN_V1 BIT(9)
#define B_BE_TXDMA_CH0_INT_EN_V1 BIT(8)
#define B_BE_RX1P1DMA_INT_EN_V1 BIT(7)
#define B_BE_RX0P1DMA_INT_EN_V1 BIT(6)
#define B_BE_RO1DMA_INT_EN BIT(5)
#define B_BE_RP1DMA_INT_EN BIT(4)
#define B_BE_RX1DMA_INT_EN BIT(3)
#define B_BE_RO0DMA_INT_EN BIT(2)
#define B_BE_RP0DMA_INT_EN BIT(1)
#define B_BE_RX0DMA_INT_EN BIT(0)
#define R_BE_HAXI_HISR00 0xB0B4
#define B_BE_RDU_CH6_INT BIT(28)
#define B_BE_RDU_CH5_INT BIT(27)
#define B_BE_RDU_CH4_INT BIT(26)
#define B_BE_RDU_CH2_INT BIT(25)
#define B_BE_RDU_CH1_INT BIT(24)
#define B_BE_RDU_CH0_INT BIT(23)
#define B_BE_RXDMA_STUCK_INT BIT(22)
#define B_BE_TXDMA_STUCK_INT BIT(21)
#define B_BE_TXDMA_CH14_INT BIT(20)
#define B_BE_TXDMA_CH13_INT BIT(19)
#define B_BE_TXDMA_CH12_INT BIT(18)
#define B_BE_TXDMA_CH11_INT BIT(17)
#define B_BE_TXDMA_CH10_INT BIT(16)
#define B_BE_TXDMA_CH9_INT BIT(15)
#define B_BE_TXDMA_CH8_INT BIT(14)
#define B_BE_TXDMA_CH7_INT BIT(13)
#define B_BE_TXDMA_CH6_INT BIT(12)
#define B_BE_TXDMA_CH5_INT BIT(11)
#define B_BE_TXDMA_CH4_INT BIT(10)
#define B_BE_TXDMA_CH3_INT BIT(9)
#define B_BE_TXDMA_CH2_INT BIT(8)
#define B_BE_TXDMA_CH1_INT BIT(7)
#define B_BE_TXDMA_CH0_INT BIT(6)
#define B_BE_RPQ1DMA_INT BIT(5)
#define B_BE_RX1P1DMA_INT BIT(4)
#define B_BE_RX1DMA_INT BIT(3)
#define B_BE_RPQ0DMA_INT BIT(2)
#define B_BE_RX0P1DMA_INT BIT(1)
#define B_BE_RX0DMA_INT BIT(0)
/* TX/RX */
#define R_AX_DRV_FW_HSK_0 0x01B0
#define R_AX_DRV_FW_HSK_1 0x01B4
@ -496,6 +724,115 @@
#define B_AX_CH11_BUSY BIT(1)
#define B_AX_CH10_BUSY BIT(0)
#define R_AX_WP_ADDR_H_SEL0_3 0x1334
#define R_AX_WP_ADDR_H_SEL4_7 0x1338
#define R_AX_WP_ADDR_H_SEL8_11 0x133C
#define R_AX_WP_ADDR_H_SEL12_15 0x1340
#define R_BE_HAXI_DMA_STOP1 0xB010
#define B_BE_STOP_WPDMA BIT(31)
#define B_BE_STOP_CH14 BIT(14)
#define B_BE_STOP_CH13 BIT(13)
#define B_BE_STOP_CH12 BIT(12)
#define B_BE_STOP_CH11 BIT(11)
#define B_BE_STOP_CH10 BIT(10)
#define B_BE_STOP_CH9 BIT(9)
#define B_BE_STOP_CH8 BIT(8)
#define B_BE_STOP_CH7 BIT(7)
#define B_BE_STOP_CH6 BIT(6)
#define B_BE_STOP_CH5 BIT(5)
#define B_BE_STOP_CH4 BIT(4)
#define B_BE_STOP_CH3 BIT(3)
#define B_BE_STOP_CH2 BIT(2)
#define B_BE_STOP_CH1 BIT(1)
#define B_BE_STOP_CH0 BIT(0)
#define B_BE_TX_STOP1_MASK (B_BE_STOP_CH0 | B_BE_STOP_CH1 | \
B_BE_STOP_CH2 | B_BE_STOP_CH3 | \
B_BE_STOP_CH4 | B_BE_STOP_CH5 | \
B_BE_STOP_CH6 | B_BE_STOP_CH7 | \
B_BE_STOP_CH8 | B_BE_STOP_CH9 | \
B_BE_STOP_CH10 | B_BE_STOP_CH11 | \
B_BE_STOP_CH12)
#define R_BE_CH0_TXBD_NUM_V1 0xB030
#define R_BE_CH1_TXBD_NUM_V1 0xB032
#define R_BE_CH2_TXBD_NUM_V1 0xB034
#define R_BE_CH3_TXBD_NUM_V1 0xB036
#define R_BE_CH4_TXBD_NUM_V1 0xB038
#define R_BE_CH5_TXBD_NUM_V1 0xB03A
#define R_BE_CH6_TXBD_NUM_V1 0xB03C
#define R_BE_CH7_TXBD_NUM_V1 0xB03E
#define R_BE_CH8_TXBD_NUM_V1 0xB040
#define R_BE_CH9_TXBD_NUM_V1 0xB042
#define R_BE_CH10_TXBD_NUM_V1 0xB044
#define R_BE_CH11_TXBD_NUM_V1 0xB046
#define R_BE_CH12_TXBD_NUM_V1 0xB048
#define R_BE_CH13_TXBD_NUM_V1 0xB04C
#define R_BE_CH14_TXBD_NUM_V1 0xB04E
#define R_BE_RXQ0_RXBD_NUM_V1 0xB050
#define R_BE_RPQ0_RXBD_NUM_V1 0xB052
#define R_BE_CH0_TXBD_IDX_V1 0xB100
#define R_BE_CH1_TXBD_IDX_V1 0xB104
#define R_BE_CH2_TXBD_IDX_V1 0xB108
#define R_BE_CH3_TXBD_IDX_V1 0xB10C
#define R_BE_CH4_TXBD_IDX_V1 0xB110
#define R_BE_CH5_TXBD_IDX_V1 0xB114
#define R_BE_CH6_TXBD_IDX_V1 0xB118
#define R_BE_CH7_TXBD_IDX_V1 0xB11C
#define R_BE_CH8_TXBD_IDX_V1 0xB120
#define R_BE_CH9_TXBD_IDX_V1 0xB124
#define R_BE_CH10_TXBD_IDX_V1 0xB128
#define R_BE_CH11_TXBD_IDX_V1 0xB12C
#define R_BE_CH12_TXBD_IDX_V1 0xB130
#define R_BE_CH13_TXBD_IDX_V1 0xB134
#define R_BE_CH14_TXBD_IDX_V1 0xB138
#define R_BE_RXQ0_RXBD_IDX_V1 0xB160
#define R_BE_RPQ0_RXBD_IDX_V1 0xB164
#define R_BE_CH0_TXBD_DESA_L_V1 0xB200
#define R_BE_CH0_TXBD_DESA_H_V1 0xB204
#define R_BE_CH1_TXBD_DESA_L_V1 0xB208
#define R_BE_CH1_TXBD_DESA_H_V1 0xB20C
#define R_BE_CH2_TXBD_DESA_L_V1 0xB210
#define R_BE_CH2_TXBD_DESA_H_V1 0xB214
#define R_BE_CH3_TXBD_DESA_L_V1 0xB218
#define R_BE_CH3_TXBD_DESA_H_V1 0xB21C
#define R_BE_CH4_TXBD_DESA_L_V1 0xB220
#define R_BE_CH4_TXBD_DESA_H_V1 0xB224
#define R_BE_CH5_TXBD_DESA_L_V1 0xB228
#define R_BE_CH5_TXBD_DESA_H_V1 0xB22C
#define R_BE_CH6_TXBD_DESA_L_V1 0xB230
#define R_BE_CH6_TXBD_DESA_H_V1 0xB234
#define R_BE_CH7_TXBD_DESA_L_V1 0xB238
#define R_BE_CH7_TXBD_DESA_H_V1 0xB23C
#define R_BE_CH8_TXBD_DESA_L_V1 0xB240
#define R_BE_CH8_TXBD_DESA_H_V1 0xB244
#define R_BE_CH9_TXBD_DESA_L_V1 0xB248
#define R_BE_CH9_TXBD_DESA_H_V1 0xB24C
#define R_BE_CH10_TXBD_DESA_L_V1 0xB250
#define R_BE_CH10_TXBD_DESA_H_V1 0xB254
#define R_BE_CH11_TXBD_DESA_L_V1 0xB258
#define R_BE_CH11_TXBD_DESA_H_V1 0xB25C
#define R_BE_CH12_TXBD_DESA_L_V1 0xB260
#define R_BE_CH12_TXBD_DESA_H_V1 0xB264
#define R_BE_CH13_TXBD_DESA_L_V1 0xB268
#define R_BE_CH13_TXBD_DESA_H_V1 0xB26C
#define R_BE_CH14_TXBD_DESA_L_V1 0xB270
#define R_BE_CH14_TXBD_DESA_H_V1 0xB274
#define R_BE_RXQ0_RXBD_DESA_L_V1 0xB300
#define R_BE_RXQ0_RXBD_DESA_H_V1 0xB304
#define R_BE_RPQ0_RXBD_DESA_L_V1 0xB308
#define R_BE_RPQ0_RXBD_DESA_H_V1 0xB30C
#define R_BE_WP_ADDR_H_SEL0_3_V1 0xB420
#define R_BE_WP_ADDR_H_SEL4_7_V1 0xB424
#define R_BE_WP_ADDR_H_SEL8_11_V1 0xB428
#define R_BE_WP_ADDR_H_SEL12_15_V1 0xB42C
/* Configure */
#define R_AX_PCIE_INIT_CFG2 0x1004
#define B_AX_WD_ITVL_IDLE GENMASK(27, 24)
@ -516,6 +853,15 @@
#define B_AX_RXCOUNTER_MATCH_MASK GENMASK(15, 8)
#define B_AX_RXTIMER_MATCH_MASK GENMASK(7, 0)
#define R_AX_DBG_ERR_FLAG_V1 0x1104
#define R_AX_INT_MIT_RX_V1 0x1184
#define B_AX_RXMIT_RXP2_SEL_V1 BIT(19)
#define B_AX_RXMIT_RXP1_SEL_V1 BIT(18)
#define B_AX_MIT_RXTIMER_UNIT_MASK GENMASK(17, 16)
#define B_AX_MIT_RXCOUNTER_MATCH_MASK GENMASK(15, 8)
#define B_AX_MIT_RXTIMER_MATCH_MASK GENMASK(7, 0)
#define R_AX_DBG_ERR_FLAG 0x11C4
#define B_AX_PCIE_RPQ_FULL BIT(29)
#define B_AX_PCIE_RXQ_FULL BIT(28)
@ -554,23 +900,160 @@
#define R_AX_PCIE_HRPWM_V1 0x30C0
#define R_AX_PCIE_CRPWM 0x30C4
#define R_AX_LBC_WATCHDOG_V1 0x30D8
#define R_BE_PCIE_HRPWM 0x30C0
#define R_BE_PCIE_CRPWM 0x30C4
#define R_BE_L1_2_CTRL_HCILDO 0x3110
#define B_BE_PCIE_DIS_L1_2_CTRL_HCILDO BIT(0)
#define R_BE_PL1_DBG_INFO 0x3120
#define B_BE_END_PL1_CNT_MASK GENMASK(23, 16)
#define B_BE_START_PL1_CNT_MASK GENMASK(7, 0)
#define R_BE_PCIE_MIT0_TMR 0x3330
#define B_BE_PCIE_MIT0_RX_TMR_MASK GENMASK(5, 4)
#define BE_MIT0_TMR_UNIT_1MS 0
#define BE_MIT0_TMR_UNIT_2MS 1
#define BE_MIT0_TMR_UNIT_4MS 2
#define BE_MIT0_TMR_UNIT_8MS 3
#define B_BE_PCIE_MIT0_TX_TMR_MASK GENMASK(1, 0)
#define R_BE_PCIE_MIT0_CNT 0x3334
#define B_BE_PCIE_RX_MIT0_CNT_MASK GENMASK(31, 24)
#define B_BE_PCIE_TX_MIT0_CNT_MASK GENMASK(23, 16)
#define B_BE_PCIE_RX_MIT0_TMR_CNT_MASK GENMASK(15, 8)
#define B_BE_PCIE_TX_MIT0_TMR_CNT_MASK GENMASK(7, 0)
#define R_BE_PCIE_MIT_CH_EN 0x3338
#define B_BE_PCIE_MIT_RX1P1_EN BIT(23)
#define B_BE_PCIE_MIT_RX0P1_EN BIT(22)
#define B_BE_PCIE_MIT_ROQ1_EN BIT(21)
#define B_BE_PCIE_MIT_RPQ1_EN BIT(20)
#define B_BE_PCIE_MIT_RX1P2_EN BIT(19)
#define B_BE_PCIE_MIT_ROQ0_EN BIT(18)
#define B_BE_PCIE_MIT_RPQ0_EN BIT(17)
#define B_BE_PCIE_MIT_RX0P2_EN BIT(16)
#define B_BE_PCIE_MIT_TXCH14_EN BIT(14)
#define B_BE_PCIE_MIT_TXCH13_EN BIT(13)
#define B_BE_PCIE_MIT_TXCH12_EN BIT(12)
#define B_BE_PCIE_MIT_TXCH11_EN BIT(11)
#define B_BE_PCIE_MIT_TXCH10_EN BIT(10)
#define B_BE_PCIE_MIT_TXCH9_EN BIT(9)
#define B_BE_PCIE_MIT_TXCH8_EN BIT(8)
#define B_BE_PCIE_MIT_TXCH7_EN BIT(7)
#define B_BE_PCIE_MIT_TXCH6_EN BIT(6)
#define B_BE_PCIE_MIT_TXCH5_EN BIT(5)
#define B_BE_PCIE_MIT_TXCH4_EN BIT(4)
#define B_BE_PCIE_MIT_TXCH3_EN BIT(3)
#define B_BE_PCIE_MIT_TXCH2_EN BIT(2)
#define B_BE_PCIE_MIT_TXCH1_EN BIT(1)
#define B_BE_PCIE_MIT_TXCH0_EN BIT(0)
#define R_BE_SER_PL1_CTRL 0x34A8
#define B_BE_PL1_SER_PL1_EN BIT(31)
#define B_BE_PL1_IGNORE_HOT_RST BIT(30)
#define B_BE_PL1_TIMER_UNIT_MASK GENMASK(19, 17)
#define B_BE_PL1_TIMER_CLEAR BIT(0)
#define R_BE_REG_PL1_MASK 0x34B0
#define B_BE_SER_PCLKREQ_ACK_MASK BIT(5)
#define B_BE_SER_PM_CLK_MASK BIT(4)
#define B_BE_SER_LTSSM_IMR BIT(3)
#define B_BE_SER_PM_MASTER_IMR BIT(2)
#define B_BE_SER_L1SUB_IMR BIT(1)
#define B_BE_SER_PMU_IMR BIT(0)
#define R_BE_REG_PL1_ISR 0x34B4
#define R_BE_RX_APPEND_MODE 0x8920
#define B_BE_APPEND_OFFSET_MASK GENMASK(23, 16)
#define B_BE_APPEND_LEN_MASK GENMASK(15, 0)
#define R_BE_TXBD_RWPTR_CLR1 0xB014
#define B_BE_CLR_CH14_IDX BIT(14)
#define B_BE_CLR_CH13_IDX BIT(13)
#define B_BE_CLR_CH12_IDX BIT(12)
#define B_BE_CLR_CH11_IDX BIT(11)
#define B_BE_CLR_CH10_IDX BIT(10)
#define B_BE_CLR_CH9_IDX BIT(9)
#define B_BE_CLR_CH8_IDX BIT(8)
#define B_BE_CLR_CH7_IDX BIT(7)
#define B_BE_CLR_CH6_IDX BIT(6)
#define B_BE_CLR_CH5_IDX BIT(5)
#define B_BE_CLR_CH4_IDX BIT(4)
#define B_BE_CLR_CH3_IDX BIT(3)
#define B_BE_CLR_CH2_IDX BIT(2)
#define B_BE_CLR_CH1_IDX BIT(1)
#define B_BE_CLR_CH0_IDX BIT(0)
#define R_BE_RXBD_RWPTR_CLR1_V1 0xB018
#define B_BE_CLR_ROQ1_IDX_V1 BIT(5)
#define B_BE_CLR_RPQ1_IDX_V1 BIT(4)
#define B_BE_CLR_RXQ1_IDX_V1 BIT(3)
#define B_BE_CLR_ROQ0_IDX BIT(2)
#define B_BE_CLR_RPQ0_IDX BIT(1)
#define B_BE_CLR_RXQ0_IDX BIT(0)
#define R_BE_HAXI_DMA_BUSY1 0xB01C
#define B_BE_HAXI_MST_BUSY BIT(31)
#define B_BE_HAXI_RX_IDLE BIT(25)
#define B_BE_HAXI_TX_IDLE BIT(24)
#define B_BE_ROQ1_BUSY_V1 BIT(21)
#define B_BE_RPQ1_BUSY_V1 BIT(20)
#define B_BE_RXQ1_BUSY_V1 BIT(19)
#define B_BE_ROQ0_BUSY_V1 BIT(18)
#define B_BE_RPQ0_BUSY_V1 BIT(17)
#define B_BE_RXQ0_BUSY_V1 BIT(16)
#define B_BE_WPDMA_BUSY BIT(15)
#define B_BE_CH14_BUSY BIT(14)
#define B_BE_CH13_BUSY BIT(13)
#define B_BE_CH12_BUSY BIT(12)
#define B_BE_CH11_BUSY BIT(11)
#define B_BE_CH10_BUSY BIT(10)
#define B_BE_CH9_BUSY BIT(9)
#define B_BE_CH8_BUSY BIT(8)
#define B_BE_CH7_BUSY BIT(7)
#define B_BE_CH6_BUSY BIT(6)
#define B_BE_CH5_BUSY BIT(5)
#define B_BE_CH4_BUSY BIT(4)
#define B_BE_CH3_BUSY BIT(3)
#define B_BE_CH2_BUSY BIT(2)
#define B_BE_CH1_BUSY BIT(1)
#define B_BE_CH0_BUSY BIT(0)
#define DMA_BUSY1_CHECK_BE (B_BE_CH0_BUSY | B_BE_CH1_BUSY | B_BE_CH2_BUSY | \
B_BE_CH3_BUSY | B_BE_CH4_BUSY | B_BE_CH5_BUSY | \
B_BE_CH6_BUSY | B_BE_CH7_BUSY | B_BE_CH8_BUSY | \
B_BE_CH9_BUSY | B_BE_CH10_BUSY | B_BE_CH11_BUSY | \
B_BE_CH12_BUSY | B_BE_CH13_BUSY | B_BE_CH14_BUSY)
#define R_BE_HAXI_EXP_CTRL_V1 0xB020
#define B_BE_R_NO_SEC_ACCESS BIT(31)
#define B_BE_FORCE_EN_DMA_RX_GCLK BIT(5)
#define B_BE_FORCE_EN_DMA_TX_GCLK BIT(4)
#define B_BE_MAX_TAG_NUM_MASK GENMASK(3, 0)
#define RTW89_PCI_TXBD_NUM_MAX 256
#define RTW89_PCI_RXBD_NUM_MAX 256
#define RTW89_PCI_TXWD_NUM_MAX 512
#define RTW89_PCI_TXWD_PAGE_SIZE 128
#define RTW89_PCI_ADDRINFO_MAX 4
#define RTW89_PCI_RX_BUF_SIZE 11460
#define RTW89_PCI_RX_BUF_SIZE (11454 + 40) /* +40 for rtw89_rxdesc_long_v2 */
#define RTW89_PCI_POLL_BDRAM_RST_CNT 100
#define RTW89_PCI_MULTITAG 8
/* PCIE CFG register */
#define RTW89_PCIE_CAPABILITY_SPEED 0x7C
#define RTW89_PCIE_SUPPORT_GEN_MASK GENMASK(3, 0)
#define RTW89_PCIE_L1_STS_V1 0x80
#define RTW89_BCFG_LINK_SPEED_MASK GENMASK(19, 16)
#define RTW89_PCIE_GEN1_SPEED 0x01
#define RTW89_PCIE_GEN2_SPEED 0x02
#define RTW89_PCIE_PHY_RATE 0x82
#define RTW89_PCIE_PHY_RATE_MASK GENMASK(1, 0)
#define RTW89_PCIE_LINK_CHANGE_SPEED 0xA0
#define RTW89_PCIE_L1SS_STS_V1 0x0168
#define RTW89_PCIE_BIT_ASPM_L11 BIT(3)
#define RTW89_PCIE_BIT_ASPM_L12 BIT(2)
@ -582,9 +1065,12 @@
#define RTW89_PCIE_TIMER_CTRL 0x0718
#define RTW89_PCIE_BIT_L1SUB BIT(5)
#define RTW89_PCIE_L1_CTRL 0x0719
#define RTW89_PCIE_BIT_EN_64BITS BIT(5)
#define RTW89_PCIE_BIT_CLK BIT(4)
#define RTW89_PCIE_BIT_L1 BIT(3)
#define RTW89_PCIE_CLK_CTRL 0x0725
#define RTW89_PCIE_FTS 0x080C
#define RTW89_PCIE_POLLING_BIT BIT(17)
#define RTW89_PCIE_RST_MSTATE 0x0B48
#define RTW89_PCIE_BIT_CFG_RST_MSTATE BIT(0)
@ -623,6 +1109,15 @@ enum rtw89_pcie_clkdly_hw {
PCIE_CLKDLY_HW_200US = 0x5,
};
enum rtw89_pcie_clkdly_hw_v1 {
PCIE_CLKDLY_HW_V1_0 = 0,
PCIE_CLKDLY_HW_V1_16US = 0x1,
PCIE_CLKDLY_HW_V1_32US = 0x2,
PCIE_CLKDLY_HW_V1_64US = 0x3,
PCIE_CLKDLY_HW_V1_80US = 0x4,
PCIE_CLKDLY_HW_V1_96US = 0x5,
};
enum mac_ax_bd_trunc_mode {
MAC_AX_BD_NORM,
MAC_AX_BD_TRUNC,
@ -757,7 +1252,34 @@ struct rtw89_pci_bd_ram {
u8 min_num;
};
struct rtw89_pci_gen_def {
u32 isr_rdu;
u32 isr_halt_c2h;
u32 isr_wdt_timeout;
struct rtw89_reg2_def isr_clear_rpq;
struct rtw89_reg2_def isr_clear_rxq;
int (*mac_pre_init)(struct rtw89_dev *rtwdev);
int (*mac_pre_deinit)(struct rtw89_dev *rtwdev);
int (*mac_post_init)(struct rtw89_dev *rtwdev);
void (*clr_idx_all)(struct rtw89_dev *rtwdev);
int (*rst_bdram)(struct rtw89_dev *rtwdev);
int (*lv1rst_stop_dma)(struct rtw89_dev *rtwdev);
int (*lv1rst_start_dma)(struct rtw89_dev *rtwdev);
void (*ctrl_txdma_ch)(struct rtw89_dev *rtwdev, bool enable);
void (*ctrl_txdma_fw_ch)(struct rtw89_dev *rtwdev, bool enable);
int (*poll_txdma_ch_idle)(struct rtw89_dev *rtwdev);
void (*aspm_set)(struct rtw89_dev *rtwdev, bool enable);
void (*clkreq_set)(struct rtw89_dev *rtwdev, bool enable);
void (*l1ss_set)(struct rtw89_dev *rtwdev, bool enable);
};
struct rtw89_pci_info {
const struct rtw89_pci_gen_def *gen_def;
enum mac_ax_bd_trunc_mode txbd_trunc_mode;
enum mac_ax_bd_trunc_mode rxbd_trunc_mode;
enum mac_ax_rxbd_mode rxbd_mode;
@ -772,6 +1294,8 @@ struct rtw89_pci_info {
enum mac_ax_pcie_func_ctrl autok_en;
enum mac_ax_pcie_func_ctrl io_rcy_en;
enum mac_ax_io_rcy_tmr io_rcy_tmr;
bool rx_ring_eq_is_full;
bool check_rx_tag;
u32 init_cfg_reg;
u32 txhci_en_bit;
@ -781,6 +1305,7 @@ struct rtw89_pci_info {
u32 max_tag_num_mask;
u32 rxbd_rwptr_clr_reg;
u32 txbd_rwptr_clr2_reg;
struct rtw89_reg_def dma_io_stop;
struct rtw89_reg_def dma_stop1;
struct rtw89_reg_def dma_stop2;
struct rtw89_reg_def dma_busy1;
@ -789,6 +1314,8 @@ struct rtw89_pci_info {
u32 rpwm_addr;
u32 cpwm_addr;
u32 mit_addr;
u32 wp_sel_addr;
u32 tx_dma_ch_mask;
const struct rtw89_pci_bd_idx_addr *bd_idx_addr_low_power;
const struct rtw89_pci_ch_dma_addr_set *dma_addr_set;
@ -812,14 +1339,14 @@ struct rtw89_pci_tx_data {
struct rtw89_pci_rx_info {
dma_addr_t dma;
u32 fs:1, ls:1, tag:11, len:14;
u32 fs:1, ls:1, tag:13, len:14;
};
#define RTW89_PCI_TXBD_OPTION_LS BIT(14)
struct rtw89_pci_tx_bd_32 {
__le16 length;
__le16 option;
__le16 opt;
#define RTW89_PCI_TXBD_OPT_LS BIT(14)
#define RTW89_PCI_TXBD_OPT_DMA_HI GENMASK(13, 6)
__le32 dma;
} __packed;
@ -834,7 +1361,7 @@ struct rtw89_pci_tx_wp_info {
#define RTW89_PCI_ADDR_MSDU_LS BIT(15)
#define RTW89_PCI_ADDR_LS BIT(14)
#define RTW89_PCI_ADDR_HIGH(a) (((a) << 6) & GENMASK(13, 6))
#define RTW89_PCI_ADDR_HIGH_MASK GENMASK(13, 6)
#define RTW89_PCI_ADDR_NUM(x) ((x) & GENMASK(5, 0))
struct rtw89_pci_tx_addr_info_32 {
@ -871,7 +1398,8 @@ struct rtw89_pci_rpp_fmt {
struct rtw89_pci_rx_bd_32 {
__le16 buf_size;
__le16 rsvd;
__le16 opt;
#define RTW89_PCI_RXBD_OPT_DMA_HI GENMASK(13, 6)
__le32 dma;
} __packed;
@ -941,6 +1469,7 @@ struct rtw89_pci_rx_ring {
u32 buf_sz;
struct sk_buff *diliver_skb;
struct rtw89_rx_desc_info diliver_desc;
u32 target_rx_tag:13;
};
struct rtw89_pci_isrs {
@ -959,6 +1488,7 @@ struct rtw89_pci {
bool running;
bool low_power;
bool under_recovery;
bool enable_dac;
struct rtw89_pci_tx_ring tx_rings[RTW89_TXCH_NUM];
struct rtw89_pci_rx_ring rx_rings[RTW89_RXCH_NUM];
struct sk_buff_head h2c_queue;
@ -1057,35 +1587,48 @@ static inline bool rtw89_pci_ltr_is_err_reg_val(u32 val)
}
extern const struct dev_pm_ops rtw89_pm_ops;
extern const struct dev_pm_ops rtw89_pm_ops_be;
extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set;
extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_v1;
extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_be;
extern const struct rtw89_pci_bd_ram rtw89_bd_ram_table_dual[RTW89_TXCH_NUM];
extern const struct rtw89_pci_bd_ram rtw89_bd_ram_table_single[RTW89_TXCH_NUM];
extern const struct rtw89_pci_gen_def rtw89_pci_gen_ax;
extern const struct rtw89_pci_gen_def rtw89_pci_gen_be;
struct pci_device_id;
int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
void rtw89_pci_remove(struct pci_dev *pdev);
void rtw89_pci_ops_reset(struct rtw89_dev *rtwdev);
int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en);
int rtw89_pci_ltr_set_v1(struct rtw89_dev *rtwdev, bool en);
int rtw89_pci_ltr_set_v2(struct rtw89_dev *rtwdev, bool en);
u32 rtw89_pci_fill_txaddr_info(struct rtw89_dev *rtwdev,
void *txaddr_info_addr, u32 total_len,
dma_addr_t dma, u8 *add_info_nr);
u32 rtw89_pci_fill_txaddr_info_v1(struct rtw89_dev *rtwdev,
void *txaddr_info_addr, u32 total_len,
dma_addr_t dma, u8 *add_info_nr);
void rtw89_pci_ctrl_dma_all(struct rtw89_dev *rtwdev, bool enable);
void rtw89_pci_config_intr_mask(struct rtw89_dev *rtwdev);
void rtw89_pci_config_intr_mask_v1(struct rtw89_dev *rtwdev);
void rtw89_pci_config_intr_mask_v2(struct rtw89_dev *rtwdev);
void rtw89_pci_enable_intr(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci);
void rtw89_pci_disable_intr(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci);
void rtw89_pci_enable_intr_v1(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci);
void rtw89_pci_disable_intr_v1(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci);
void rtw89_pci_enable_intr_v2(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci);
void rtw89_pci_disable_intr_v2(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci);
void rtw89_pci_recognize_intrs(struct rtw89_dev *rtwdev,
struct rtw89_pci *rtwpci,
struct rtw89_pci_isrs *isrs);
void rtw89_pci_recognize_intrs_v1(struct rtw89_dev *rtwdev,
struct rtw89_pci *rtwpci,
struct rtw89_pci_isrs *isrs);
void rtw89_pci_recognize_intrs_v2(struct rtw89_dev *rtwdev,
struct rtw89_pci *rtwpci,
struct rtw89_pci_isrs *isrs);
static inline
u32 rtw89_chip_fill_txaddr_info(struct rtw89_dev *rtwdev,
@ -1157,4 +1700,70 @@ void rtw89_chip_recognize_intrs(struct rtw89_dev *rtwdev,
info->recognize_intrs(rtwdev, rtwpci, isrs);
}
static inline int rtw89_pci_ops_mac_pre_init(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
const struct rtw89_pci_gen_def *gen_def = info->gen_def;
return gen_def->mac_pre_init(rtwdev);
}
static inline int rtw89_pci_ops_mac_pre_deinit(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
const struct rtw89_pci_gen_def *gen_def = info->gen_def;
if (!gen_def->mac_pre_deinit)
return 0;
return gen_def->mac_pre_deinit(rtwdev);
}
static inline int rtw89_pci_ops_mac_post_init(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
const struct rtw89_pci_gen_def *gen_def = info->gen_def;
return gen_def->mac_post_init(rtwdev);
}
static inline void rtw89_pci_clr_idx_all(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
const struct rtw89_pci_gen_def *gen_def = info->gen_def;
gen_def->clr_idx_all(rtwdev);
}
static inline int rtw89_pci_reset_bdram(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
const struct rtw89_pci_gen_def *gen_def = info->gen_def;
return gen_def->rst_bdram(rtwdev);
}
static inline void rtw89_pci_ctrl_txdma_ch(struct rtw89_dev *rtwdev, bool enable)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
const struct rtw89_pci_gen_def *gen_def = info->gen_def;
return gen_def->ctrl_txdma_ch(rtwdev, enable);
}
static inline void rtw89_pci_ctrl_txdma_fw_ch(struct rtw89_dev *rtwdev, bool enable)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
const struct rtw89_pci_gen_def *gen_def = info->gen_def;
return gen_def->ctrl_txdma_fw_ch(rtwdev, enable);
}
static inline int rtw89_pci_poll_txdma_ch_idle(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
const struct rtw89_pci_gen_def *gen_def = info->gen_def;
return gen_def->poll_txdma_ch_idle(rtwdev);
}
#endif

618
pci_be.c Normal file
View File

@ -0,0 +1,618 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2023 Realtek Corporation
*/
#include <linux/pci.h>
#include "mac.h"
#include "pci.h"
#include "reg.h"
enum pcie_rxbd_mode {
PCIE_RXBD_NORM = 0,
PCIE_RXBD_SEP,
PCIE_RXBD_EXT,
};
#define PL0_TMR_SCALE_ASIC 1
#define PL0_TMR_ANA_172US 0x800
#define PL0_TMR_MAC_1MS 0x27100
#define PL0_TMR_AUX_1MS 0x1E848
static void rtw89_pci_aspm_set_be(struct rtw89_dev *rtwdev, bool enable)
{
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
struct pci_dev *pdev = rtwpci->pdev;
u8 value = 0;
int ret;
ret = pci_read_config_byte(pdev, RTW89_PCIE_ASPM_CTRL, &value);
if (ret)
rtw89_warn(rtwdev, "failed to read ASPM Delay\n");
u8p_replace_bits(&value, PCIE_L1DLY_16US, RTW89_L1DLY_MASK);
ret = pci_write_config_byte(pdev, RTW89_PCIE_ASPM_CTRL, value);
if (ret)
rtw89_warn(rtwdev, "failed to write ASPM Delay\n");
if (enable)
rtw89_write32_set(rtwdev, R_AX_PCIE_MIX_CFG_V1,
B_BE_ASPM_CTRL_L1);
else
rtw89_write32_clr(rtwdev, R_AX_PCIE_MIX_CFG_V1,
B_BE_ASPM_CTRL_L1);
}
static void rtw89_pci_l1ss_set_be(struct rtw89_dev *rtwdev, bool enable)
{
if (enable)
rtw89_write32_set(rtwdev, R_BE_PCIE_MIX_CFG,
B_BE_L1SUB_ENABLE);
else
rtw89_write32_clr(rtwdev, R_BE_PCIE_MIX_CFG,
B_BE_L1SUB_ENABLE);
}
static void rtw89_pci_clkreq_set_be(struct rtw89_dev *rtwdev, bool enable)
{
rtw89_write32_mask(rtwdev, R_BE_PCIE_LAT_CTRL, B_BE_CLK_REQ_LAT_MASK,
PCIE_CLKDLY_HW_V1_0);
if (enable)
rtw89_write32_set(rtwdev, R_BE_L1_CLK_CTRL,
B_BE_CLK_PM_EN);
else
rtw89_write32_clr(rtwdev, R_AX_L1_CLK_CTRL,
B_BE_CLK_PM_EN);
}
static void _patch_pcie_power_wake_be(struct rtw89_dev *rtwdev, bool power_up)
{
if (power_up)
rtw89_write32_set(rtwdev, R_BE_HCI_OPT_CTRL, BIT_WAKE_CTRL_V1);
else
rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, BIT_WAKE_CTRL_V1);
}
static void rtw89_pci_set_io_rcy_be(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
u32 scale = PL0_TMR_SCALE_ASIC;
u32 val32;
if (info->io_rcy_en == MAC_AX_PCIE_ENABLE) {
val32 = info->io_rcy_tmr == MAC_AX_IO_RCY_ANA_TMR_DEF ?
PL0_TMR_ANA_172US : info->io_rcy_tmr;
val32 /= scale;
rtw89_write32(rtwdev, R_BE_AON_WDT_TMR, val32);
rtw89_write32(rtwdev, R_BE_MDIO_WDT_TMR, val32);
rtw89_write32(rtwdev, R_BE_LA_MODE_WDT_TMR, val32);
rtw89_write32(rtwdev, R_BE_WDT_AR_TMR, val32);
rtw89_write32(rtwdev, R_BE_WDT_AW_TMR, val32);
rtw89_write32(rtwdev, R_BE_WDT_W_TMR, val32);
rtw89_write32(rtwdev, R_BE_WDT_B_TMR, val32);
rtw89_write32(rtwdev, R_BE_WDT_R_TMR, val32);
val32 = info->io_rcy_tmr == MAC_AX_IO_RCY_ANA_TMR_DEF ?
PL0_TMR_MAC_1MS : info->io_rcy_tmr;
val32 /= scale;
rtw89_write32(rtwdev, R_BE_WLAN_WDT_TMR, val32);
rtw89_write32(rtwdev, R_BE_AXIDMA_WDT_TMR, val32);
val32 = info->io_rcy_tmr == MAC_AX_IO_RCY_ANA_TMR_DEF ?
PL0_TMR_AUX_1MS : info->io_rcy_tmr;
val32 /= scale;
rtw89_write32(rtwdev, R_BE_LOCAL_WDT_TMR, val32);
} else {
rtw89_write32_clr(rtwdev, R_BE_WLAN_WDT, B_BE_WLAN_WDT_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_AXIDMA_WDT, B_BE_AXIDMA_WDT_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_AON_WDT, B_BE_AON_WDT_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_LOCAL_WDT, B_BE_LOCAL_WDT_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_MDIO_WDT, B_BE_MDIO_WDT_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_LA_MODE_WDT, B_BE_LA_MODE_WDT_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_WDT_AR, B_BE_WDT_AR_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_WDT_AW, B_BE_WDT_AW_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_WDT_W, B_BE_WDT_W_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_WDT_B, B_BE_WDT_B_ENABLE);
rtw89_write32_clr(rtwdev, R_BE_WDT_R, B_BE_WDT_R_ENABLE);
}
}
static void rtw89_pci_ctrl_wpdma_pcie_be(struct rtw89_dev *rtwdev, bool en)
{
if (en)
rtw89_write32_clr(rtwdev, R_BE_HAXI_DMA_STOP1, B_BE_STOP_WPDMA);
else
rtw89_write32_set(rtwdev, R_BE_HAXI_DMA_STOP1, B_BE_STOP_WPDMA);
}
static void rtw89_pci_ctrl_trxdma_pcie_be(struct rtw89_dev *rtwdev,
enum mac_ax_pcie_func_ctrl tx_en,
enum mac_ax_pcie_func_ctrl rx_en,
enum mac_ax_pcie_func_ctrl io_en)
{
u32 val;
val = rtw89_read32(rtwdev, R_BE_HAXI_INIT_CFG1);
if (tx_en == MAC_AX_PCIE_ENABLE)
val |= B_BE_TXDMA_EN;
else if (tx_en == MAC_AX_PCIE_DISABLE)
val &= ~B_BE_TXDMA_EN;
if (rx_en == MAC_AX_PCIE_ENABLE)
val |= B_BE_RXDMA_EN;
else if (rx_en == MAC_AX_PCIE_DISABLE)
val &= ~B_BE_RXDMA_EN;
if (io_en == MAC_AX_PCIE_ENABLE)
val &= ~B_BE_STOP_AXI_MST;
else if (io_en == MAC_AX_PCIE_DISABLE)
val |= B_BE_STOP_AXI_MST;
rtw89_write32(rtwdev, R_BE_HAXI_INIT_CFG1, val);
if (io_en == MAC_AX_PCIE_ENABLE)
rtw89_write32_mask(rtwdev, R_BE_HAXI_MST_WDT_TIMEOUT_SEL_V1,
B_BE_HAXI_MST_WDT_TIMEOUT_SEL_MASK, 4);
}
static void rtw89_pci_clr_idx_all_be(struct rtw89_dev *rtwdev)
{
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
struct rtw89_pci_rx_ring *rx_ring;
u32 val;
val = B_BE_CLR_CH0_IDX | B_BE_CLR_CH1_IDX | B_BE_CLR_CH2_IDX |
B_BE_CLR_CH3_IDX | B_BE_CLR_CH4_IDX | B_BE_CLR_CH5_IDX |
B_BE_CLR_CH6_IDX | B_BE_CLR_CH7_IDX | B_BE_CLR_CH8_IDX |
B_BE_CLR_CH9_IDX | B_BE_CLR_CH10_IDX | B_BE_CLR_CH11_IDX |
B_BE_CLR_CH12_IDX | B_BE_CLR_CH13_IDX | B_BE_CLR_CH14_IDX;
rtw89_write32(rtwdev, R_BE_TXBD_RWPTR_CLR1, val);
rtw89_write32(rtwdev, R_BE_RXBD_RWPTR_CLR1_V1,
B_BE_CLR_RXQ0_IDX | B_BE_CLR_RPQ0_IDX);
rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RXQ];
rtw89_write16(rtwdev, R_BE_RXQ0_RXBD_IDX_V1, rx_ring->bd_ring.len - 1);
rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RPQ];
rtw89_write16(rtwdev, R_BE_RPQ0_RXBD_IDX_V1, rx_ring->bd_ring.len - 1);
}
static int rtw89_pci_poll_txdma_ch_idle_be(struct rtw89_dev *rtwdev)
{
u32 val;
return read_poll_timeout(rtw89_read32, val, (val & DMA_BUSY1_CHECK_BE) == 0,
10, 1000, false, rtwdev, R_BE_HAXI_DMA_BUSY1);
}
static int rtw89_pci_poll_rxdma_ch_idle_be(struct rtw89_dev *rtwdev)
{
u32 check;
u32 val;
check = B_BE_RXQ0_BUSY_V1 | B_BE_RPQ0_BUSY_V1;
return read_poll_timeout(rtw89_read32, val, (val & check) == 0,
10, 1000, false, rtwdev, R_BE_HAXI_DMA_BUSY1);
}
static int rtw89_pci_poll_dma_all_idle_be(struct rtw89_dev *rtwdev)
{
int ret;
ret = rtw89_pci_poll_txdma_ch_idle_be(rtwdev);
if (ret) {
rtw89_err(rtwdev, "txdma ch busy\n");
return ret;
}
ret = rtw89_pci_poll_rxdma_ch_idle_be(rtwdev);
if (ret) {
rtw89_err(rtwdev, "rxdma ch busy\n");
return ret;
}
return 0;
}
static void rtw89_pci_mode_op_be(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
u32 val32_init1, val32_rxapp, val32_exp;
val32_init1 = rtw89_read32(rtwdev, R_BE_HAXI_INIT_CFG1);
val32_rxapp = rtw89_read32(rtwdev, R_BE_RX_APPEND_MODE);
val32_exp = rtw89_read32(rtwdev, R_BE_HAXI_EXP_CTRL_V1);
if (info->rxbd_mode == MAC_AX_RXBD_PKT) {
val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_NORM,
B_BE_RXQ_RXBD_MODE_MASK);
} else if (info->rxbd_mode == MAC_AX_RXBD_SEP) {
val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_SEP,
B_BE_RXQ_RXBD_MODE_MASK);
val32_rxapp = u32_replace_bits(val32_rxapp, 0,
B_BE_APPEND_LEN_MASK);
}
val32_init1 = u32_replace_bits(val32_init1, info->tx_burst,
B_BE_MAX_TXDMA_MASK);
val32_init1 = u32_replace_bits(val32_init1, info->rx_burst,
B_BE_MAX_RXDMA_MASK);
val32_exp = u32_replace_bits(val32_exp, info->multi_tag_num,
B_BE_MAX_TAG_NUM_MASK);
val32_init1 = u32_replace_bits(val32_init1, info->wd_dma_idle_intvl,
B_BE_CFG_WD_PERIOD_IDLE_MASK);
val32_init1 = u32_replace_bits(val32_init1, info->wd_dma_act_intvl,
B_BE_CFG_WD_PERIOD_ACTIVE_MASK);
rtw89_write32(rtwdev, R_BE_HAXI_INIT_CFG1, val32_init1);
rtw89_write32(rtwdev, R_BE_RX_APPEND_MODE, val32_rxapp);
rtw89_write32(rtwdev, R_BE_HAXI_EXP_CTRL_V1, val32_exp);
}
static int rtw89_pci_rst_bdram_be(struct rtw89_dev *rtwdev)
{
u32 val;
rtw89_write32_set(rtwdev, R_BE_HAXI_INIT_CFG1, B_BE_SET_BDRAM_BOUND);
return read_poll_timeout(rtw89_read32, val, !(val & B_BE_SET_BDRAM_BOUND),
50, 500000, false, rtwdev, R_BE_HAXI_INIT_CFG1);
}
static void rtw89_pci_debounce_be(struct rtw89_dev *rtwdev)
{
u32 val32;
val32 = rtw89_read32(rtwdev, R_BE_SYS_PAGE_CLK_GATED);
val32 = u32_replace_bits(val32, 0, B_BE_PCIE_PRST_DEBUNC_PERIOD_MASK);
val32 |= B_BE_SYM_PRST_DEBUNC_SEL;
rtw89_write32(rtwdev, R_BE_SYS_PAGE_CLK_GATED, val32);
}
static void rtw89_pci_ldo_low_pwr_be(struct rtw89_dev *rtwdev)
{
rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_PSUS_OFF_CAPC_EN);
rtw89_write32_set(rtwdev, R_BE_SYS_PAGE_CLK_GATED,
B_BE_SOP_OFFPOOBS_PC | B_BE_CPHY_AUXCLK_OP |
B_BE_CPHY_POWER_READY_CHK);
rtw89_write32_clr(rtwdev, R_BE_SYS_SDIO_CTRL, B_BE_PCIE_FORCE_IBX_EN |
B_BE_PCIE_DIS_L2_RTK_PERST |
B_BE_PCIE_DIS_L2__CTRL_LDO_HCI);
rtw89_write32_clr(rtwdev, R_BE_L1_2_CTRL_HCILDO, B_BE_PCIE_DIS_L1_2_CTRL_HCILDO);
}
static void rtw89_pci_pcie_setting_be(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_hal *hal = &rtwdev->hal;
rtw89_write32_set(rtwdev, R_BE_PCIE_FRZ_CLK, B_BE_PCIE_EN_AUX_CLK);
rtw89_write32_clr(rtwdev, R_BE_PCIE_PS_CTRL, B_BE_CMAC_EXIT_L1_EN);
if (chip->chip_id == RTL8922A && hal->cv == CHIP_CAV)
return;
rtw89_write32_set(rtwdev, R_BE_EFUSE_CTRL_2_V1, B_BE_R_SYM_AUTOLOAD_WITH_PMC_SEL);
rtw89_write32_set(rtwdev, R_BE_PCIE_LAT_CTRL, B_BE_SYM_AUX_CLK_SEL);
}
static void rtw89_pci_ser_setting_be(struct rtw89_dev *rtwdev)
{
u32 val32;
rtw89_write32(rtwdev, R_BE_PL1_DBG_INFO, 0x0);
rtw89_write32_set(rtwdev, R_BE_FWS1IMR, B_BE_PCIE_SER_TIMEOUT_INDIC_EN);
rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN);
rtw89_write32_mask(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_TIMER_UNIT_MASK, 1);
val32 = rtw89_read32(rtwdev, R_BE_REG_PL1_MASK);
val32 |= B_BE_SER_PMU_IMR | B_BE_SER_L1SUB_IMR | B_BE_SER_PM_MASTER_IMR |
B_BE_SER_LTSSM_IMR | B_BE_SER_PM_CLK_MASK | B_BE_SER_PCLKREQ_ACK_MASK;
rtw89_write32(rtwdev, R_BE_REG_PL1_MASK, val32);
}
static void rtw89_pci_ctrl_txdma_ch_be(struct rtw89_dev *rtwdev, bool enable)
{
u32 mask_all;
u32 val;
mask_all = B_BE_STOP_CH0 | B_BE_STOP_CH1 | B_BE_STOP_CH2 |
B_BE_STOP_CH3 | B_BE_STOP_CH4 | B_BE_STOP_CH5 |
B_BE_STOP_CH6 | B_BE_STOP_CH7 | B_BE_STOP_CH8 |
B_BE_STOP_CH9 | B_BE_STOP_CH10 | B_BE_STOP_CH11;
val = rtw89_read32(rtwdev, R_BE_HAXI_DMA_STOP1);
val |= B_BE_STOP_CH13 | B_BE_STOP_CH14;
if (enable)
val &= ~mask_all;
else
val |= mask_all;
rtw89_write32(rtwdev, R_BE_HAXI_DMA_STOP1, val);
}
static void rtw89_pci_ctrl_txdma_fw_ch_be(struct rtw89_dev *rtwdev, bool enable)
{
u32 val = rtw89_read32(rtwdev, R_BE_HAXI_DMA_STOP1);
if (enable)
val &= ~B_BE_STOP_CH12;
else
val |= B_BE_STOP_CH12;
rtw89_write32(rtwdev, R_BE_HAXI_DMA_STOP1, val);
}
static int rtw89_pci_ops_mac_pre_init_be(struct rtw89_dev *rtwdev)
{
int ret;
rtw89_pci_set_io_rcy_be(rtwdev);
_patch_pcie_power_wake_be(rtwdev, true);
rtw89_pci_ctrl_wpdma_pcie_be(rtwdev, false);
rtw89_pci_ctrl_trxdma_pcie_be(rtwdev, MAC_AX_PCIE_DISABLE,
MAC_AX_PCIE_DISABLE, MAC_AX_PCIE_DISABLE);
rtw89_pci_clr_idx_all_be(rtwdev);
ret = rtw89_pci_poll_dma_all_idle_be(rtwdev);
if (ret) {
rtw89_err(rtwdev, "[ERR] poll pcie dma all idle\n");
return ret;
}
rtw89_pci_mode_op_be(rtwdev);
rtw89_pci_ops_reset(rtwdev);
ret = rtw89_pci_rst_bdram_be(rtwdev);
if (ret) {
rtw89_err(rtwdev, "[ERR]pcie rst bdram\n");
return ret;
}
rtw89_pci_debounce_be(rtwdev);
rtw89_pci_ldo_low_pwr_be(rtwdev);
rtw89_pci_pcie_setting_be(rtwdev);
rtw89_pci_ser_setting_be(rtwdev);
rtw89_pci_ctrl_txdma_ch_be(rtwdev, false);
rtw89_pci_ctrl_txdma_fw_ch_be(rtwdev, true);
rtw89_pci_ctrl_trxdma_pcie_be(rtwdev, MAC_AX_PCIE_ENABLE,
MAC_AX_PCIE_ENABLE, MAC_AX_PCIE_ENABLE);
return 0;
}
static int rtw89_pci_ops_mac_pre_deinit_be(struct rtw89_dev *rtwdev)
{
u32 val;
_patch_pcie_power_wake_be(rtwdev, false);
val = rtw89_read32_mask(rtwdev, R_BE_IC_PWR_STATE, B_BE_WLMAC_PWR_STE_MASK);
if (val == 0)
return 0;
rtw89_pci_ctrl_trxdma_pcie_be(rtwdev, MAC_AX_PCIE_DISABLE,
MAC_AX_PCIE_DISABLE, MAC_AX_PCIE_DISABLE);
rtw89_pci_clr_idx_all_be(rtwdev);
return 0;
}
int rtw89_pci_ltr_set_v2(struct rtw89_dev *rtwdev, bool en)
{
u32 ctrl0, cfg0, cfg1, dec_ctrl, idle_ltcy, act_ltcy, dis_ltcy;
ctrl0 = rtw89_read32(rtwdev, R_BE_LTR_CTRL_0);
if (rtw89_pci_ltr_is_err_reg_val(ctrl0))
return -EINVAL;
cfg0 = rtw89_read32(rtwdev, R_BE_LTR_CFG_0);
if (rtw89_pci_ltr_is_err_reg_val(cfg0))
return -EINVAL;
cfg1 = rtw89_read32(rtwdev, R_BE_LTR_CFG_1);
if (rtw89_pci_ltr_is_err_reg_val(cfg1))
return -EINVAL;
dec_ctrl = rtw89_read32(rtwdev, R_BE_LTR_DECISION_CTRL_V1);
if (rtw89_pci_ltr_is_err_reg_val(dec_ctrl))
return -EINVAL;
idle_ltcy = rtw89_read32(rtwdev, R_BE_LTR_LATENCY_IDX3_V1);
if (rtw89_pci_ltr_is_err_reg_val(idle_ltcy))
return -EINVAL;
act_ltcy = rtw89_read32(rtwdev, R_BE_LTR_LATENCY_IDX1_V1);
if (rtw89_pci_ltr_is_err_reg_val(act_ltcy))
return -EINVAL;
dis_ltcy = rtw89_read32(rtwdev, R_BE_LTR_LATENCY_IDX0_V1);
if (rtw89_pci_ltr_is_err_reg_val(dis_ltcy))
return -EINVAL;
if (en) {
dec_ctrl |= B_BE_ENABLE_LTR_CTL_DECISION | B_BE_LTR_HW_DEC_EN_V1;
ctrl0 |= B_BE_LTR_HW_EN;
} else {
dec_ctrl &= ~(B_BE_ENABLE_LTR_CTL_DECISION | B_BE_LTR_HW_DEC_EN_V1 |
B_BE_LTR_EN_PORT_V1_MASK);
ctrl0 &= ~B_BE_LTR_HW_EN;
}
dec_ctrl = u32_replace_bits(dec_ctrl, PCI_LTR_SPC_500US,
B_BE_LTR_SPACE_IDX_MASK);
cfg0 = u32_replace_bits(cfg0, PCI_LTR_IDLE_TIMER_3_2MS,
B_BE_LTR_IDLE_TIMER_IDX_MASK);
cfg1 = u32_replace_bits(cfg1, 0xC0, B_BE_LTR_CMAC0_RX_USE_PG_TH_MASK);
cfg1 = u32_replace_bits(cfg1, 0xC0, B_BE_LTR_CMAC1_RX_USE_PG_TH_MASK);
cfg0 = u32_replace_bits(cfg0, 1, B_BE_LTR_IDX_ACTIVE_MASK);
cfg0 = u32_replace_bits(cfg0, 3, B_BE_LTR_IDX_IDLE_MASK);
dec_ctrl = u32_replace_bits(dec_ctrl, 0, B_BE_LTR_IDX_DISABLE_V1_MASK);
rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX3_V1, 0x90039003);
rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX1_V1, 0x880b880b);
rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX0_V1, 0);
rtw89_write32(rtwdev, R_BE_LTR_DECISION_CTRL_V1, dec_ctrl);
rtw89_write32(rtwdev, R_BE_LTR_CFG_0, cfg0);
rtw89_write32(rtwdev, R_BE_LTR_CFG_1, cfg1);
rtw89_write32(rtwdev, R_BE_LTR_CTRL_0, ctrl0);
return 0;
}
EXPORT_SYMBOL(rtw89_pci_ltr_set_v2);
static void rtw89_pci_configure_mit_be(struct rtw89_dev *rtwdev)
{
u32 cnt;
u32 val;
rtw89_write32_mask(rtwdev, R_BE_PCIE_MIT0_TMR,
B_BE_PCIE_MIT0_RX_TMR_MASK, BE_MIT0_TMR_UNIT_1MS);
val = rtw89_read32(rtwdev, R_BE_PCIE_MIT0_CNT);
cnt = min_t(u32, U8_MAX, RTW89_PCI_RXBD_NUM_MAX / 2);
val = u32_replace_bits(val, cnt, B_BE_PCIE_RX_MIT0_CNT_MASK);
val = u32_replace_bits(val, 2, B_BE_PCIE_RX_MIT0_TMR_CNT_MASK);
rtw89_write32(rtwdev, R_BE_PCIE_MIT0_CNT, val);
}
static int rtw89_pci_ops_mac_post_init_be(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
int ret;
ret = info->ltr_set(rtwdev, true);
if (ret) {
rtw89_err(rtwdev, "pci ltr set fail\n");
return ret;
}
rtw89_pci_ctrl_trxdma_pcie_be(rtwdev, MAC_AX_PCIE_IGNORE,
MAC_AX_PCIE_IGNORE, MAC_AX_PCIE_ENABLE);
rtw89_pci_ctrl_wpdma_pcie_be(rtwdev, true);
rtw89_pci_ctrl_txdma_ch_be(rtwdev, true);
rtw89_pci_ctrl_txdma_fw_ch_be(rtwdev, true);
rtw89_pci_configure_mit_be(rtwdev);
return 0;
}
static int rtw89_pci_poll_io_idle_be(struct rtw89_dev *rtwdev)
{
u32 sts;
int ret;
ret = read_poll_timeout_atomic(rtw89_read32, sts,
!(sts & B_BE_HAXI_MST_BUSY),
10, 1000, false, rtwdev,
R_BE_HAXI_DMA_BUSY1);
if (ret) {
rtw89_err(rtwdev, "pci dmach busy1 0x%X\n", sts);
return ret;
}
return 0;
}
static int rtw89_pci_lv1rst_stop_dma_be(struct rtw89_dev *rtwdev)
{
int ret;
rtw89_pci_ctrl_dma_all(rtwdev, false);
ret = rtw89_pci_poll_io_idle_be(rtwdev);
if (!ret)
return 0;
rtw89_debug(rtwdev, RTW89_DBG_HCI,
"[PCIe] poll_io_idle fail; reset hci dma trx\n");
rtw89_mac_ctrl_hci_dma_trx(rtwdev, false);
rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
return rtw89_pci_poll_io_idle_be(rtwdev);
}
static int rtw89_pci_lv1rst_start_dma_be(struct rtw89_dev *rtwdev)
{
int ret;
rtw89_mac_ctrl_hci_dma_trx(rtwdev, false);
rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
rtw89_pci_clr_idx_all(rtwdev);
ret = rtw89_pci_rst_bdram_be(rtwdev);
if (ret)
return ret;
rtw89_pci_ctrl_dma_all(rtwdev, true);
return 0;
}
static int __maybe_unused rtw89_pci_suspend_be(struct device *dev)
{
struct ieee80211_hw *hw = dev_get_drvdata(dev);
struct rtw89_dev *rtwdev = hw->priv;
rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_R_DIS_PRST);
rtw89_write32_clr(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
rtw89_write32_set(rtwdev, R_BE_PCIE_FRZ_CLK, B_BE_PCIE_FRZ_REG_RST);
rtw89_write32_clr(rtwdev, R_BE_REG_PL1_MASK, B_BE_SER_PM_MASTER_IMR);
return 0;
}
static int __maybe_unused rtw89_pci_resume_be(struct device *dev)
{
struct ieee80211_hw *hw = dev_get_drvdata(dev);
struct rtw89_dev *rtwdev = hw->priv;
u32 polling;
int ret;
rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
rtw89_write32_clr(rtwdev, R_BE_RSV_CTRL, B_BE_R_DIS_PRST);
rtw89_write32_clr(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
rtw89_write32_clr(rtwdev, R_BE_PCIE_FRZ_CLK, B_BE_PCIE_FRZ_REG_RST);
rtw89_write32_clr(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN);
ret = read_poll_timeout_atomic(rtw89_read32, polling, !polling, 1, 1000,
false, rtwdev, R_BE_REG_PL1_ISR);
if (ret)
rtw89_warn(rtwdev, "[ERR] PCIE SER clear polling fail\n");
rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN);
rtw89_write32_set(rtwdev, R_BE_REG_PL1_MASK, B_BE_SER_PM_MASTER_IMR);
return 0;
}
SIMPLE_DEV_PM_OPS(rtw89_pm_ops_be, rtw89_pci_suspend_be, rtw89_pci_resume_be);
EXPORT_SYMBOL(rtw89_pm_ops_be);
const struct rtw89_pci_gen_def rtw89_pci_gen_be = {
.isr_rdu = B_BE_RDU_CH1_INT | B_BE_RDU_CH0_INT,
.isr_halt_c2h = B_BE_HALT_C2H_INT,
.isr_wdt_timeout = B_BE_WDT_TIMEOUT_INT,
.isr_clear_rpq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RPQ0_ISR_V1},
.isr_clear_rxq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RX0P2_ISR_V1},
.mac_pre_init = rtw89_pci_ops_mac_pre_init_be,
.mac_pre_deinit = rtw89_pci_ops_mac_pre_deinit_be,
.mac_post_init = rtw89_pci_ops_mac_post_init_be,
.clr_idx_all = rtw89_pci_clr_idx_all_be,
.rst_bdram = rtw89_pci_rst_bdram_be,
.lv1rst_stop_dma = rtw89_pci_lv1rst_stop_dma_be,
.lv1rst_start_dma = rtw89_pci_lv1rst_start_dma_be,
.ctrl_txdma_ch = rtw89_pci_ctrl_txdma_ch_be,
.ctrl_txdma_fw_ch = rtw89_pci_ctrl_txdma_fw_ch_be,
.poll_txdma_ch_idle = rtw89_pci_poll_txdma_ch_idle_be,
.aspm_set = rtw89_pci_aspm_set_be,
.clkreq_set = rtw89_pci_clkreq_set_be,
.l1ss_set = rtw89_pci_l1ss_set_be,
};
EXPORT_SYMBOL(rtw89_pci_gen_be);

2523
phy.c

File diff suppressed because it is too large Load Diff

429
phy.h
View File

@ -7,7 +7,7 @@
#include "core.h"
#define RTW89_PHY_ADDR_OFFSET 0x10000
#define RTW89_BBMCU_ADDR_OFFSET 0x30000
#define RTW89_RF_ADDR_ADSEL_MASK BIT(16)
#define get_phy_headline(addr) FIELD_GET(GENMASK(31, 28), addr)
@ -47,6 +47,11 @@
#define RA_MASK_HE_3SS_RATES GENMASK_ULL(47, 36)
#define RA_MASK_HE_4SS_RATES GENMASK_ULL(59, 48)
#define RA_MASK_HE_RATES GENMASK_ULL(59, 12)
#define RA_MASK_EHT_1SS_RATES GENMASK_ULL(27, 12)
#define RA_MASK_EHT_2SS_RATES GENMASK_ULL(43, 28)
#define RA_MASK_EHT_3SS_RATES GENMASK_ULL(59, 44)
#define RA_MASK_EHT_4SS_RATES GENMASK_ULL(62, 60)
#define RA_MASK_EHT_RATES GENMASK_ULL(62, 12)
#define CFO_TRK_ENABLE_TH (2 << 2)
#define CFO_TRK_STOP_TH_4 (30 << 2)
@ -118,6 +123,14 @@
#define PHYSTS_RSVD BIT(RTW89_RX_TYPE_RSVD)
#define PPDU_FILTER_BITMAP (PHYSTS_MGNT | PHYSTS_DATA)
#define EDCCA_MAX 249
#define EDCCA_TH_L2H_LB 66
#define EDCCA_TH_REF 3
#define EDCCA_HL_DIFF_NORMAL 8
#define RSSI_UNIT_CONVER 110
#define EDCCA_UNIT_CONVER 128
#define EDCCA_PWROFST_DEFAULT 18
enum rtw89_phy_c2h_ra_func {
RTW89_PHY_C2H_FUNC_STS_RPT,
RTW89_PHY_C2H_FUNC_MU_GPTBL_RPT,
@ -125,6 +138,21 @@ enum rtw89_phy_c2h_ra_func {
RTW89_PHY_C2H_FUNC_RA_MAX,
};
enum rtw89_phy_c2h_rfk_log_func {
RTW89_PHY_C2H_RFK_LOG_FUNC_IQK = 0,
RTW89_PHY_C2H_RFK_LOG_FUNC_DPK = 1,
RTW89_PHY_C2H_RFK_LOG_FUNC_DACK = 2,
RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK = 3,
RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI = 4,
RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK = 5,
RTW89_PHY_C2H_RFK_LOG_FUNC_NUM,
};
enum rtw89_phy_c2h_rfk_report_func {
RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE = 0,
};
enum rtw89_phy_c2h_dm_func {
RTW89_PHY_C2H_DM_FUNC_FW_TEST,
RTW89_PHY_C2H_DM_FUNC_FW_TRIG_TX_RPT,
@ -138,6 +166,8 @@ enum rtw89_phy_c2h_class {
RTW89_PHY_C2H_CLASS_RUA,
RTW89_PHY_C2H_CLASS_RA,
RTW89_PHY_C2H_CLASS_DM,
RTW89_PHY_C2H_RFK_LOG = 0x8,
RTW89_PHY_C2H_RFK_REPORT = 0x9,
RTW89_PHY_C2H_CLASS_BTC_MIN = 0x10,
RTW89_PHY_C2H_CLASS_BTC_MAX = 0x17,
RTW89_PHY_C2H_CLASS_MAX,
@ -280,8 +310,6 @@ struct rtw89_txpwr_byrate_cfg {
u32 data;
};
#define DELTA_SWINGIDX_SIZE 30
struct rtw89_txpwr_track_cfg {
const s8 (*delta_swingidx_6gb_n)[DELTA_SWINGIDX_SIZE];
const s8 (*delta_swingidx_6gb_p)[DELTA_SWINGIDX_SIZE];
@ -337,61 +365,262 @@ struct rtw89_nbi_reg_def {
struct rtw89_reg_def notch2_en;
};
struct rtw89_ccx_regs {
u32 setting_addr;
u32 edcca_opt_mask;
u32 measurement_trig_mask;
u32 trig_opt_mask;
u32 en_mask;
u32 ifs_cnt_addr;
u32 ifs_clm_period_mask;
u32 ifs_clm_cnt_unit_mask;
u32 ifs_clm_cnt_clear_mask;
u32 ifs_collect_en_mask;
u32 ifs_t1_addr;
u32 ifs_t1_th_h_mask;
u32 ifs_t1_en_mask;
u32 ifs_t1_th_l_mask;
u32 ifs_t2_addr;
u32 ifs_t2_th_h_mask;
u32 ifs_t2_en_mask;
u32 ifs_t2_th_l_mask;
u32 ifs_t3_addr;
u32 ifs_t3_th_h_mask;
u32 ifs_t3_en_mask;
u32 ifs_t3_th_l_mask;
u32 ifs_t4_addr;
u32 ifs_t4_th_h_mask;
u32 ifs_t4_en_mask;
u32 ifs_t4_th_l_mask;
u32 ifs_clm_tx_cnt_addr;
u32 ifs_clm_edcca_excl_cca_fa_mask;
u32 ifs_clm_tx_cnt_msk;
u32 ifs_clm_cca_addr;
u32 ifs_clm_ofdmcca_excl_fa_mask;
u32 ifs_clm_cckcca_excl_fa_mask;
u32 ifs_clm_fa_addr;
u32 ifs_clm_ofdm_fa_mask;
u32 ifs_clm_cck_fa_mask;
u32 ifs_his_addr;
u32 ifs_t4_his_mask;
u32 ifs_t3_his_mask;
u32 ifs_t2_his_mask;
u32 ifs_t1_his_mask;
u32 ifs_avg_l_addr;
u32 ifs_t2_avg_mask;
u32 ifs_t1_avg_mask;
u32 ifs_avg_h_addr;
u32 ifs_t4_avg_mask;
u32 ifs_t3_avg_mask;
u32 ifs_cca_l_addr;
u32 ifs_t2_cca_mask;
u32 ifs_t1_cca_mask;
u32 ifs_cca_h_addr;
u32 ifs_t4_cca_mask;
u32 ifs_t3_cca_mask;
u32 ifs_total_addr;
u32 ifs_cnt_done_mask;
u32 ifs_total_mask;
};
struct rtw89_physts_regs {
u32 setting_addr;
u32 dis_trigger_fail_mask;
u32 dis_trigger_brk_mask;
};
struct rtw89_cfo_regs {
u32 comp;
u32 weighting_mask;
u32 comp_seg0;
u32 valid_0_mask;
};
enum rtw89_bandwidth_section_num_ax {
RTW89_BW20_SEC_NUM_AX = 8,
RTW89_BW40_SEC_NUM_AX = 4,
RTW89_BW80_SEC_NUM_AX = 2,
};
enum rtw89_bandwidth_section_num_be {
RTW89_BW20_SEC_NUM_BE = 16,
RTW89_BW40_SEC_NUM_BE = 8,
RTW89_BW80_SEC_NUM_BE = 4,
RTW89_BW160_SEC_NUM_BE = 2,
};
#define RTW89_TXPWR_LMT_PAGE_SIZE_AX 40
struct rtw89_txpwr_limit_ax {
s8 cck_20m[RTW89_BF_NUM];
s8 cck_40m[RTW89_BF_NUM];
s8 ofdm[RTW89_BF_NUM];
s8 mcs_20m[RTW89_BW20_SEC_NUM_AX][RTW89_BF_NUM];
s8 mcs_40m[RTW89_BW40_SEC_NUM_AX][RTW89_BF_NUM];
s8 mcs_80m[RTW89_BW80_SEC_NUM_AX][RTW89_BF_NUM];
s8 mcs_160m[RTW89_BF_NUM];
s8 mcs_40m_0p5[RTW89_BF_NUM];
s8 mcs_40m_2p5[RTW89_BF_NUM];
};
#define RTW89_TXPWR_LMT_PAGE_SIZE_BE 76
struct rtw89_txpwr_limit_be {
s8 cck_20m[RTW89_BF_NUM];
s8 cck_40m[RTW89_BF_NUM];
s8 ofdm[RTW89_BF_NUM];
s8 mcs_20m[RTW89_BW20_SEC_NUM_BE][RTW89_BF_NUM];
s8 mcs_40m[RTW89_BW40_SEC_NUM_BE][RTW89_BF_NUM];
s8 mcs_80m[RTW89_BW80_SEC_NUM_BE][RTW89_BF_NUM];
s8 mcs_160m[RTW89_BW160_SEC_NUM_BE][RTW89_BF_NUM];
s8 mcs_320m[RTW89_BF_NUM];
s8 mcs_40m_0p5[RTW89_BF_NUM];
s8 mcs_40m_2p5[RTW89_BF_NUM];
s8 mcs_40m_4p5[RTW89_BF_NUM];
s8 mcs_40m_6p5[RTW89_BF_NUM];
};
#define RTW89_RU_SEC_NUM_AX 8
#define RTW89_TXPWR_LMT_RU_PAGE_SIZE_AX 24
struct rtw89_txpwr_limit_ru_ax {
s8 ru26[RTW89_RU_SEC_NUM_AX];
s8 ru52[RTW89_RU_SEC_NUM_AX];
s8 ru106[RTW89_RU_SEC_NUM_AX];
};
#define RTW89_RU_SEC_NUM_BE 16
#define RTW89_TXPWR_LMT_RU_PAGE_SIZE_BE 80
struct rtw89_txpwr_limit_ru_be {
s8 ru26[RTW89_RU_SEC_NUM_BE];
s8 ru52[RTW89_RU_SEC_NUM_BE];
s8 ru106[RTW89_RU_SEC_NUM_BE];
s8 ru52_26[RTW89_RU_SEC_NUM_BE];
s8 ru106_26[RTW89_RU_SEC_NUM_BE];
};
struct rtw89_phy_rfk_log_fmt {
const struct rtw89_fw_element_hdr *elm[RTW89_PHY_C2H_RFK_LOG_FUNC_NUM];
};
struct rtw89_phy_gen_def {
u32 cr_base;
const struct rtw89_ccx_regs *ccx;
const struct rtw89_physts_regs *physts;
const struct rtw89_cfo_regs *cfo;
u32 (*phy0_phy1_offset)(struct rtw89_dev *rtwdev, u32 addr);
void (*config_bb_gain)(struct rtw89_dev *rtwdev,
const struct rtw89_reg2_def *reg,
enum rtw89_rf_path rf_path,
void *extra_data);
void (*preinit_rf_nctl)(struct rtw89_dev *rtwdev);
void (*bb_wrap_init)(struct rtw89_dev *rtwdev);
void (*ch_info_init)(struct rtw89_dev *rtwdev);
void (*set_txpwr_byrate)(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
void (*set_txpwr_offset)(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
void (*set_txpwr_limit)(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
void (*set_txpwr_limit_ru)(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
};
extern const struct rtw89_phy_gen_def rtw89_phy_gen_ax;
extern const struct rtw89_phy_gen_def rtw89_phy_gen_be;
static inline void rtw89_phy_write8(struct rtw89_dev *rtwdev,
u32 addr, u8 data)
{
rtw89_write8(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, data);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
rtw89_write8(rtwdev, addr + phy->cr_base, data);
}
static inline void rtw89_phy_write16(struct rtw89_dev *rtwdev,
u32 addr, u16 data)
{
rtw89_write16(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, data);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
rtw89_write16(rtwdev, addr + phy->cr_base, data);
}
static inline void rtw89_phy_write32(struct rtw89_dev *rtwdev,
u32 addr, u32 data)
{
rtw89_write32(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, data);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
rtw89_write32(rtwdev, addr + phy->cr_base, data);
}
static inline void rtw89_phy_write32_set(struct rtw89_dev *rtwdev,
u32 addr, u32 bits)
{
rtw89_write32_set(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, bits);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
rtw89_write32_set(rtwdev, addr + phy->cr_base, bits);
}
static inline void rtw89_phy_write32_clr(struct rtw89_dev *rtwdev,
u32 addr, u32 bits)
{
rtw89_write32_clr(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, bits);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
rtw89_write32_clr(rtwdev, addr + phy->cr_base, bits);
}
static inline void rtw89_phy_write32_mask(struct rtw89_dev *rtwdev,
u32 addr, u32 mask, u32 data)
{
rtw89_write32_mask(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, mask, data);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
rtw89_write32_mask(rtwdev, addr + phy->cr_base, mask, data);
}
static inline u8 rtw89_phy_read8(struct rtw89_dev *rtwdev, u32 addr)
{
return rtw89_read8(rtwdev, addr | RTW89_PHY_ADDR_OFFSET);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
return rtw89_read8(rtwdev, addr + phy->cr_base);
}
static inline u16 rtw89_phy_read16(struct rtw89_dev *rtwdev, u32 addr)
{
return rtw89_read16(rtwdev, addr | RTW89_PHY_ADDR_OFFSET);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
return rtw89_read16(rtwdev, addr + phy->cr_base);
}
static inline u32 rtw89_phy_read32(struct rtw89_dev *rtwdev, u32 addr)
{
return rtw89_read32(rtwdev, addr | RTW89_PHY_ADDR_OFFSET);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
return rtw89_read32(rtwdev, addr + phy->cr_base);
}
static inline u32 rtw89_phy_read32_mask(struct rtw89_dev *rtwdev,
u32 addr, u32 mask)
{
return rtw89_read32_mask(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, mask);
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
return rtw89_read32_mask(rtwdev, addr + phy->cr_base, mask);
}
static inline void rtw89_bbmcu_write32(struct rtw89_dev *rtwdev,
u32 addr, u32 data, enum rtw89_phy_idx phy_idx)
{
if (phy_idx && addr < 0x10000)
addr += 0x20000;
rtw89_write32(rtwdev, addr + RTW89_BBMCU_ADDR_OFFSET, data);
}
static inline
@ -407,6 +636,22 @@ enum rtw89_gain_offset rtw89_subband_to_gain_offset_band_of_ofdm(enum rtw89_subb
return RTW89_GAIN_OFFSET_5G_MID;
case RTW89_CH_5G_BAND_4:
return RTW89_GAIN_OFFSET_5G_HIGH;
case RTW89_CH_6G_BAND_IDX0:
return RTW89_GAIN_OFFSET_6G_L0;
case RTW89_CH_6G_BAND_IDX1:
return RTW89_GAIN_OFFSET_6G_L1;
case RTW89_CH_6G_BAND_IDX2:
return RTW89_GAIN_OFFSET_6G_M0;
case RTW89_CH_6G_BAND_IDX3:
return RTW89_GAIN_OFFSET_6G_M1;
case RTW89_CH_6G_BAND_IDX4:
return RTW89_GAIN_OFFSET_6G_H0;
case RTW89_CH_6G_BAND_IDX5:
return RTW89_GAIN_OFFSET_6G_H1;
case RTW89_CH_6G_BAND_IDX6:
return RTW89_GAIN_OFFSET_6G_UH0;
case RTW89_CH_6G_BAND_IDX7:
return RTW89_GAIN_OFFSET_6G_UH1;
}
}
@ -438,6 +683,51 @@ enum rtw89_phy_bb_gain_band rtw89_subband_to_bb_gain_band(enum rtw89_subband sub
}
}
static inline
enum rtw89_phy_gain_band_be rtw89_subband_to_gain_band_be(enum rtw89_subband subband)
{
switch (subband) {
default:
case RTW89_CH_2G:
return RTW89_BB_GAIN_BAND_2G_BE;
case RTW89_CH_5G_BAND_1:
return RTW89_BB_GAIN_BAND_5G_L_BE;
case RTW89_CH_5G_BAND_3:
return RTW89_BB_GAIN_BAND_5G_M_BE;
case RTW89_CH_5G_BAND_4:
return RTW89_BB_GAIN_BAND_5G_H_BE;
case RTW89_CH_6G_BAND_IDX0:
return RTW89_BB_GAIN_BAND_6G_L0_BE;
case RTW89_CH_6G_BAND_IDX1:
return RTW89_BB_GAIN_BAND_6G_L1_BE;
case RTW89_CH_6G_BAND_IDX2:
return RTW89_BB_GAIN_BAND_6G_M0_BE;
case RTW89_CH_6G_BAND_IDX3:
return RTW89_BB_GAIN_BAND_6G_M1_BE;
case RTW89_CH_6G_BAND_IDX4:
return RTW89_BB_GAIN_BAND_6G_H0_BE;
case RTW89_CH_6G_BAND_IDX5:
return RTW89_BB_GAIN_BAND_6G_H1_BE;
case RTW89_CH_6G_BAND_IDX6:
return RTW89_BB_GAIN_BAND_6G_UH0_BE;
case RTW89_CH_6G_BAND_IDX7:
return RTW89_BB_GAIN_BAND_6G_UH1_BE;
}
}
struct rtw89_rfk_chan_desc {
/* desc is valid iff ch is non-zero */
u8 ch;
/* To avoid us from extending old chip code every time, each new
* field must be defined along with a bool flag in positivte way.
*/
bool has_band;
u8 band;
bool has_bw;
u8 bw;
};
enum rtw89_rfk_flag {
RTW89_RFK_F_WRF = 0,
RTW89_RFK_F_WM = 1,
@ -502,14 +792,20 @@ void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_bandwidth dbw);
u8 rtw89_phy_get_txsb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
enum rtw89_bandwidth dbw);
u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask);
u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask);
u32 rtw89_phy_read_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask);
bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask, u32 data);
bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask, u32 data);
bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask, u32 data);
void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev);
void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio);
void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
@ -521,22 +817,81 @@ void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
u32 data, enum rtw89_phy_idx phy_idx);
u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
enum rtw89_phy_idx phy_idx);
s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev,
struct rtw89_txpwr_byrate *head,
const struct rtw89_rate_desc *desc);
s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band, u8 bw,
const struct rtw89_rate_desc *rate_desc);
void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
const struct rtw89_txpwr_table *tbl);
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch);
s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
u8 ru, u8 ntx, u8 ch);
static inline void rtw89_phy_preinit_rf_nctl(struct rtw89_dev *rtwdev)
{
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
phy->preinit_rf_nctl(rtwdev);
}
static inline void rtw89_phy_bb_wrap_init(struct rtw89_dev *rtwdev)
{
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
if (phy->bb_wrap_init)
phy->bb_wrap_init(rtwdev);
}
static inline void rtw89_phy_ch_info_init(struct rtw89_dev *rtwdev)
{
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
if (phy->ch_info_init)
phy->ch_info_init(rtwdev);
}
static inline
void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
enum rtw89_phy_idx phy_idx)
{
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
phy->set_txpwr_byrate(rtwdev, chan, phy_idx);
}
static inline
void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
enum rtw89_phy_idx phy_idx)
{
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
phy->set_txpwr_offset(rtwdev, chan, phy_idx);
}
static inline
void rtw89_phy_set_txpwr_limit(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
enum rtw89_phy_idx phy_idx)
{
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
phy->set_txpwr_limit(rtwdev, chan, phy_idx);
}
static inline
void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
enum rtw89_phy_idx phy_idx)
{
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
phy->set_txpwr_limit_ru(rtwdev, chan, phy_idx);
}
void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta);
void rtw89_phy_ra_update(struct rtw89_dev *rtwdev);
void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
@ -544,8 +899,39 @@ void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta
void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask);
bool rtw89_phy_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func);
void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
u32 len, u8 class, u8 func);
int rtw89_phy_rfk_pre_ntfy_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
unsigned int ms);
int rtw89_phy_rfk_tssi_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
enum rtw89_tssi_mode tssi_mode,
unsigned int ms);
int rtw89_phy_rfk_iqk_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
unsigned int ms);
int rtw89_phy_rfk_dpk_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
unsigned int ms);
int rtw89_phy_rfk_txgapk_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
unsigned int ms);
int rtw89_phy_rfk_dack_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
unsigned int ms);
int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
unsigned int ms);
void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy,
const struct rtw89_chan *chan,
struct rtw89_h2c_rf_tssi *h2c);
void rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy,
const struct rtw89_chan *chan,
struct rtw89_h2c_rf_tssi *h2c);
void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev);
void rtw89_phy_cfo_track_work(struct work_struct *work);
void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val,
@ -571,5 +957,14 @@ u8 rtw89_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band);
void rtw89_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx,
u8 *ch, enum nl80211_band *band);
void rtw89_phy_config_edcca(struct rtw89_dev *rtwdev, bool scan);
void rtw89_phy_edcca_track(struct rtw89_dev *rtwdev);
void rtw89_phy_edcca_thre_calc(struct rtw89_dev *rtwdev);
enum rtw89_rf_path_bit rtw89_phy_get_kpath(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx);
enum rtw89_rf_path rtw89_phy_get_syn_sel(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx);
u8 rtw89_rfk_chan_lookup(struct rtw89_dev *rtwdev,
const struct rtw89_rfk_chan_desc *desc, u8 desc_nr,
const struct rtw89_chan *target_chan);
#endif

1002
phy_be.c Normal file

File diff suppressed because it is too large Load Diff

88
ps.c
View File

@ -2,6 +2,7 @@
/* Copyright(c) 2019-2020 Realtek Corporation
*/
#include "chan.h"
#include "coex.h"
#include "core.h"
#include "debug.h"
@ -13,6 +14,7 @@
static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 pwr_en_bit = 0xE;
u32 chk_msk = pwr_en_bit << (4 * macid);
u32 polling;
@ -20,7 +22,7 @@ static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid)
ret = read_poll_timeout_atomic(rtw89_read32_mask, polling, !polling,
1000, 50000, false, rtwdev,
R_AX_PPWRBIT_SETTING, chk_msk);
mac->ps_status, chk_msk);
if (ret) {
rtw89_info(rtwdev, "rtw89: failed to leave lps state\n");
return -EBUSY;
@ -53,7 +55,8 @@ static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
{
if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode))
if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
!test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
else
rtw89_mac_power_mode_change(rtwdev, enter);
@ -82,16 +85,17 @@ void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
rtw89_ps_power_mode_change(rtwdev, false);
}
static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, u8 mac_id)
static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
{
struct rtw89_lps_parm lps_param = {
.macid = mac_id,
.macid = rtwvif->mac_id,
.psmode = RTW89_MAC_AX_PS_MODE_LEGACY,
.lastrpwm = RTW89_LAST_RPWM_PS,
};
rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL);
rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif);
}
static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, u8 mac_id)
@ -122,7 +126,7 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
return;
__rtw89_enter_lps(rtwdev, rtwvif->mac_id);
__rtw89_enter_lps(rtwdev, rtwvif);
if (ps_mode)
__rtw89_enter_ps_mode(rtwdev, rtwvif);
}
@ -257,8 +261,13 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev)
{
struct ieee80211_vif *vif, *found_vif = NULL;
struct rtw89_vif *rtwvif;
enum rtw89_entity_mode mode;
int count = 0;
mode = rtw89_get_entity_mode(rtwdev);
if (mode == RTW89_ENTITY_MODE_MCC)
goto disable_lps;
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
vif = rtwvif_to_vif(rtwvif);
@ -273,8 +282,71 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev)
if (count == 1 && found_vif->cfg.ps) {
rtwdev->lps_enabled = true;
} else {
rtw89_leave_lps(rtwdev);
rtwdev->lps_enabled = false;
return;
}
disable_lps:
rtw89_leave_lps(rtwdev);
rtwdev->lps_enabled = false;
}
void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif)
{
struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa;
struct rtw89_p2p_noa_ie *ie = &setter->ie;
struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head;
struct rtw89_noa_attr_head *noa_head = &ie->noa_head;
if (setter->noa_count) {
setter->noa_index++;
setter->noa_count = 0;
}
memset(ie, 0, sizeof(*ie));
p2p_head->eid = WLAN_EID_VENDOR_SPECIFIC;
p2p_head->ie_len = 4 + sizeof(*noa_head);
p2p_head->oui[0] = (WLAN_OUI_WFA >> 16) & 0xff;
p2p_head->oui[1] = (WLAN_OUI_WFA >> 8) & 0xff;
p2p_head->oui[2] = (WLAN_OUI_WFA >> 0) & 0xff;
p2p_head->oui_type = WLAN_OUI_TYPE_WFA_P2P;
noa_head->attr_type = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
noa_head->attr_len = cpu_to_le16(2);
noa_head->index = setter->noa_index;
noa_head->oppps_ctwindow = 0;
}
void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif,
const struct ieee80211_p2p_noa_desc *desc)
{
struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa;
struct rtw89_p2p_noa_ie *ie = &setter->ie;
struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head;
struct rtw89_noa_attr_head *noa_head = &ie->noa_head;
if (!desc->count || !desc->duration)
return;
if (setter->noa_count >= RTW89_P2P_MAX_NOA_NUM)
return;
p2p_head->ie_len += sizeof(*desc);
le16_add_cpu(&noa_head->attr_len, sizeof(*desc));
ie->noa_desc[setter->noa_count++] = *desc;
}
u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data)
{
struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa;
struct rtw89_p2p_noa_ie *ie = &setter->ie;
void *tail;
if (!setter->noa_count)
return 0;
*data = ie;
tail = ie->noa_desc + setter->noa_count;
return tail - *data;
}

8
ps.h
View File

@ -16,6 +16,10 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev);
void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl);
void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
void rtw89_recalc_lps(struct rtw89_dev *rtwdev);
void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif);
void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif,
const struct ieee80211_p2p_noa_desc *desc);
u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data);
static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev)
{
@ -29,6 +33,10 @@ static inline void rtw89_enter_ips_by_hwflags(struct rtw89_dev *rtwdev)
{
struct ieee80211_hw *hw = rtwdev->hw;
/* prevent entering IPS after ROC, but it is scanning */
if (rtwdev->scanning)
return;
if (hw->conf.flags & IEEE80211_CONF_IDLE)
rtw89_enter_ips(rtwdev);
}

4292
reg.h

File diff suppressed because it is too large Load Diff

550
regd.c
View File

@ -13,10 +13,10 @@
}
static const struct rtw89_regd rtw89_ww_regd =
COUNTRY_REGD("00", RTW89_WW, RTW89_WW);
COUNTRY_REGD("00", RTW89_WW, RTW89_WW, RTW89_WW);
static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA),
COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC),
COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE),
@ -26,7 +26,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA),
COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC),
COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA),
@ -81,7 +81,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
@ -96,7 +96,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE),
COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
@ -112,10 +112,10 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_ETSI),
COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_THAILAND),
COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
@ -148,7 +148,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@ -164,7 +164,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@ -185,14 +185,15 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("IM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("JE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("KI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("XK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@ -207,7 +208,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("NP", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@ -256,7 +257,42 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
};
static const struct rtw89_regd *rtw89_regd_find_reg_by_name(char *alpha2)
static const char rtw89_alpha2_list_eu[][3] = {
"AT",
"BE",
"CY",
"CZ",
"DK",
"EE",
"FI",
"FR",
"DE",
"GR",
"HU",
"IS",
"IE",
"IT",
"LV",
"LI",
"LT",
"LU",
"MT",
"MC",
"NL",
"NO",
"PL",
"PT",
"SK",
"SI",
"ES",
"SE",
"CH",
"BG",
"HR",
"RO",
};
static const struct rtw89_regd *rtw89_regd_find_reg_by_name(const char *alpha2)
{
u32 i;
@ -273,6 +309,24 @@ static bool rtw89_regd_is_ww(const struct rtw89_regd *regd)
return regd == &rtw89_ww_regd;
}
static u8 rtw89_regd_get_index(const struct rtw89_regd *regd)
{
BUILD_BUG_ON(ARRAY_SIZE(rtw89_regd_map) > RTW89_REGD_MAX_COUNTRY_NUM);
if (rtw89_regd_is_ww(regd))
return RTW89_REGD_MAX_COUNTRY_NUM;
return regd - rtw89_regd_map;
}
static u8 rtw89_regd_get_index_by_name(const char *alpha2)
{
const struct rtw89_regd *regd;
regd = rtw89_regd_find_reg_by_name(alpha2);
return rtw89_regd_get_index(regd);
}
#define rtw89_debug_regd(_dev, _regd, _desc, _argv...) \
do { \
typeof(_regd) __r = _regd; \
@ -287,48 +341,176 @@ do { \
static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev,
struct wiphy *wiphy)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_chip_info *chip = rtwdev->chip;
bool regd_allow_unii_4 = chip->support_unii4;
struct ieee80211_supported_band *sband;
struct rtw89_acpi_dsm_result res = {};
bool enable_by_fcc;
bool enable_by_ic;
int ret;
u8 val;
if (!chip->support_unii4)
goto bottom;
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_59G_EN, &val);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: cannot eval unii 4: %d\n", ret);
goto bottom;
}
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: eval if allow unii 4: %d\n", val);
switch (val) {
case 0:
regd_allow_unii_4 = false;
break;
case 1:
regd_allow_unii_4 = true;
break;
default:
break;
}
bottom:
rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow unii 4: %d\n",
regd_allow_unii_4);
if (regd_allow_unii_4)
return;
int i;
sband = wiphy->bands[NL80211_BAND_5GHZ];
if (!sband)
return;
sband->n_channels -= 3;
if (!chip->support_unii4) {
sband->n_channels -= RTW89_5GHZ_UNII4_CHANNEL_NUM;
return;
}
bitmap_fill(regulatory->block_unii4, RTW89_REGD_MAX_COUNTRY_NUM);
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_UNII4_SUP, &res);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: cannot eval unii 4: %d\n", ret);
enable_by_fcc = true;
enable_by_ic = false;
goto bottom;
}
val = res.u.value;
enable_by_fcc = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_FCC);
enable_by_ic = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_IC);
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: eval if allow unii-4: 0x%x\n", val);
bottom:
for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) {
const struct rtw89_regd *regd = &rtw89_regd_map[i];
switch (regd->txpwr_regd[RTW89_BAND_5G]) {
case RTW89_FCC:
if (enable_by_fcc)
clear_bit(i, regulatory->block_unii4);
break;
case RTW89_IC:
if (enable_by_ic)
clear_bit(i, regulatory->block_unii4);
break;
default:
break;
}
}
}
static void __rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev, bool block,
const char *alpha2)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
u8 index;
index = rtw89_regd_get_index_by_name(alpha2);
if (index == RTW89_REGD_MAX_COUNTRY_NUM) {
rtw89_debug(rtwdev, RTW89_DBG_REGD, "%s: unknown alpha2 %c%c\n",
__func__, alpha2[0], alpha2[1]);
return;
}
if (block)
set_bit(index, regulatory->block_6ghz);
else
clear_bit(index, regulatory->block_6ghz);
}
static void rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_acpi_country_code *country;
const struct rtw89_acpi_policy_6ghz *ptr;
struct rtw89_acpi_dsm_result res = {};
bool to_block;
int i, j;
int ret;
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_BP, &res);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: cannot eval policy 6ghz: %d\n", ret);
return;
}
ptr = res.u.policy_6ghz;
switch (ptr->policy_mode) {
case RTW89_ACPI_POLICY_BLOCK:
to_block = true;
break;
case RTW89_ACPI_POLICY_ALLOW:
to_block = false;
/* only below list is allowed; block all first */
bitmap_fill(regulatory->block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM);
break;
default:
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"%s: unknown policy mode: %d\n", __func__,
ptr->policy_mode);
goto out;
}
for (i = 0; i < ptr->country_count; i++) {
country = &ptr->country_list[i];
if (memcmp("EU", country->alpha2, 2) != 0) {
__rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
country->alpha2);
continue;
}
for (j = 0; j < ARRAY_SIZE(rtw89_alpha2_list_eu); j++)
__rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
rtw89_alpha2_list_eu[j]);
}
out:
kfree(ptr);
}
static void rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev *rtwdev)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_acpi_policy_6ghz_sp *ptr;
struct rtw89_acpi_dsm_result res = {};
bool enable_by_us;
int ret;
int i;
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, &res);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: cannot eval policy 6ghz-sp: %d\n", ret);
return;
}
ptr = res.u.policy_6ghz_sp;
switch (ptr->override) {
default:
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"%s: unknown override case: %d\n", __func__,
ptr->override);
fallthrough;
case 0:
goto out;
case 1:
break;
}
bitmap_fill(regulatory->block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM);
enable_by_us = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_US);
for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) {
const struct rtw89_regd *tmp = &rtw89_regd_map[i];
if (enable_by_us && memcmp(tmp->alpha2, "US", 2) == 0)
clear_bit(i, regulatory->block_6ghz_sp);
}
out:
kfree(ptr);
}
static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
@ -337,19 +519,22 @@ static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ);
bool regd_allow_6ghz = chip_support_6ghz;
struct ieee80211_supported_band *sband;
struct rtw89_acpi_dsm_result res = {};
int ret;
u8 val;
if (!chip_support_6ghz)
goto bottom;
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &val);
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &res);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: cannot eval 6ghz: %d\n", ret);
goto bottom;
}
val = res.u.value;
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: eval if disallow 6ghz: %d\n", val);
@ -368,15 +553,18 @@ static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n",
regd_allow_6ghz);
if (regd_allow_6ghz)
if (regd_allow_6ghz) {
rtw89_regd_setup_policy_6ghz(rtwdev);
rtw89_regd_setup_policy_6ghz_sp(rtwdev);
return;
}
sband = wiphy->bands[NL80211_BAND_6GHZ];
if (!sband)
return;
wiphy->bands[NL80211_BAND_6GHZ] = NULL;
kfree(sband->iftype_data);
kfree((__force void *)sband->iftype_data);
kfree(sband);
}
@ -429,6 +617,60 @@ int rtw89_regd_init(struct rtw89_dev *rtwdev,
return 0;
}
static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev,
struct wiphy *wiphy)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_regd *regd = regulatory->regd;
struct ieee80211_supported_band *sband;
u8 index;
int i;
sband = wiphy->bands[NL80211_BAND_5GHZ];
if (!sband)
return;
if (!chip->support_unii4)
return;
index = rtw89_regd_get_index(regd);
if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
!test_bit(index, regulatory->block_unii4))
return;
rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c unii-4 is blocked by policy\n",
regd->alpha2[0], regd->alpha2[1]);
for (i = RTW89_5GHZ_UNII4_START_INDEX; i < sband->n_channels; i++)
sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
}
static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
struct wiphy *wiphy)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_regd *regd = regulatory->regd;
struct ieee80211_supported_band *sband;
u8 index;
int i;
index = rtw89_regd_get_index(regd);
if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
!test_bit(index, regulatory->block_6ghz))
return;
rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is blocked by policy\n",
regd->alpha2[0], regd->alpha2[1]);
sband = wiphy->bands[NL80211_BAND_6GHZ];
if (!sband)
return;
for (i = 0; i < sband->n_channels; i++)
sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
}
static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
struct wiphy *wiphy,
struct regulatory_request *request)
@ -443,6 +685,9 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
else
wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
rtw89_regd_apply_policy_unii4(rtwdev, wiphy);
rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
}
void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
@ -469,13 +714,162 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
mutex_unlock(&rtwdev->mutex);
}
static void __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
/* Maximum Transmit Power field (@raw) can be EIRP or PSD.
* Both units are 0.5 dB-based. Return a constraint in dB.
*/
static s8 tpe_get_constraint(s8 raw)
{
const u8 hw_deviation = 3; /* unit: 0.5 dB */
const u8 antenna_gain = 10; /* unit: 0.5 dB */
const u8 array_gain = 6; /* unit: 0.5 dB */
const u8 offset = hw_deviation + antenna_gain + array_gain;
return (raw - offset) / 2;
}
static void tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe *tpe, s8 cstr)
{
if (tpe->valid) {
tpe->constraint = min(tpe->constraint, cstr);
return;
}
tpe->constraint = cstr;
tpe->valid = true;
}
static void tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe *tpe,
const struct ieee80211_parsed_tpe_eirp *eirp)
{
unsigned int i;
s8 cstr;
if (!eirp->valid)
return;
for (i = 0; i < eirp->count; i++) {
cstr = tpe_get_constraint(eirp->power[i]);
tpe_intersect_constraint(tpe, cstr);
}
}
static s8 tpe_convert_psd_to_eirp(s8 psd)
{
static const unsigned int mlog20 = 1301;
return psd + 10 * mlog20 / 1000;
}
static void tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe *tpe,
const struct ieee80211_parsed_tpe_psd *psd)
{
unsigned int i;
s8 cstr_psd;
s8 cstr;
if (!psd->valid)
return;
for (i = 0; i < psd->count; i++) {
cstr_psd = tpe_get_constraint(psd->power[i]);
cstr = tpe_convert_psd_to_eirp(cstr_psd);
tpe_intersect_constraint(tpe, cstr);
}
}
static void rtw89_calculate_tpe(struct rtw89_dev *rtwdev,
struct rtw89_reg_6ghz_tpe *result_tpe,
const struct ieee80211_parsed_tpe *parsed_tpe)
{
static const u8 category = IEEE80211_TPE_CAT_6GHZ_DEFAULT;
tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_local[category]);
tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_reg_client[category]);
tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_local[category]);
tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_reg_client[category]);
}
static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
struct rtw89_reg_6ghz_tpe new = {};
struct rtw89_vif *rtwvif;
bool changed = false;
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
const struct rtw89_reg_6ghz_tpe *tmp;
const struct rtw89_chan *chan;
chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
if (chan->band_type != RTW89_BAND_6G)
continue;
tmp = &rtwvif->reg_6ghz_tpe;
if (!tmp->valid)
continue;
tpe_intersect_constraint(&new, tmp->constraint);
}
if (memcmp(&regulatory->reg_6ghz_tpe, &new,
sizeof(regulatory->reg_6ghz_tpe)) != 0)
changed = true;
if (changed) {
if (new.valid)
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"recalc 6 GHz reg TPE to %d dBm\n",
new.constraint);
else
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"recalc 6 GHz reg TPE to none\n");
regulatory->reg_6ghz_tpe = new;
}
return changed;
}
static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif, bool active,
unsigned int *changed)
{
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct rtw89_reg_6ghz_tpe *tpe = &rtwvif->reg_6ghz_tpe;
memset(tpe, 0, sizeof(*tpe));
if (!active || rtwvif->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD)
goto bottom;
rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe);
if (!tpe->valid)
goto bottom;
if (tpe->constraint < RTW89_MIN_VALID_POWER_CONSTRAINT) {
rtw89_err(rtwdev,
"%s: constraint %d dBm is less than min valid val\n",
__func__, tpe->constraint);
tpe->valid = false;
return -EINVAL;
}
bottom:
*changed += __rtw89_reg_6ghz_tpe_recalc(rtwdev);
return 0;
}
static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_regd *regd = regulatory->regd;
enum rtw89_reg_6ghz_power sel;
const struct rtw89_chan *chan;
struct rtw89_vif *rtwvif;
int count = 0;
u8 index;
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
@ -492,24 +886,33 @@ static void __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
if (count != 1)
sel = RTW89_REG_6GHZ_POWER_DFLT;
if (sel == RTW89_REG_6GHZ_POWER_STD) {
index = rtw89_regd_get_index(regd);
if (index == RTW89_REGD_MAX_COUNTRY_NUM ||
test_bit(index, regulatory->block_6ghz_sp)) {
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"%c%c 6 GHz SP is blocked by policy\n",
regd->alpha2[0], regd->alpha2[1]);
sel = RTW89_REG_6GHZ_POWER_DFLT;
}
}
if (regulatory->reg_6ghz_power == sel)
return;
return false;
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"recalc 6 GHz reg power type to %d\n", sel);
regulatory->reg_6ghz_power = sel;
rtw89_core_set_chip_txpwr(rtwdev);
return true;
}
void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif, bool active)
static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif, bool active,
unsigned int *changed)
{
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
lockdep_assert_held(&rtwdev->mutex);
if (active) {
switch (vif->bss_conf.power_type) {
case IEEE80211_REG_VLP_AP:
@ -529,5 +932,32 @@ void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
}
__rtw89_reg_6ghz_power_recalc(rtwdev);
*changed += __rtw89_reg_6ghz_power_recalc(rtwdev);
return 0;
}
int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
bool active)
{
unsigned int changed = 0;
int ret;
lockdep_assert_held(&rtwdev->mutex);
/* The result of reg_6ghz_tpe may depend on reg_6ghz_power type,
* so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc().
*/
ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, active, &changed);
if (ret)
return ret;
ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif, active, &changed);
if (ret)
return ret;
if (changed)
rtw89_core_set_chip_txpwr(rtwdev);
return 0;
}

View File

@ -105,6 +105,10 @@ static const u32 rtw8851b_c2h_regs[RTW89_C2HREG_MAX] = {
R_AX_C2HREG_DATA3
};
static const u32 rtw8851b_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = {
R_AX_C2HREG_DATA3 + 3, R_AX_C2HREG_DATA3 + 3,
};
static const struct rtw89_page_regs rtw8851b_page_regs = {
.hci_fc_ctrl = R_AX_HCI_FC_CTRL,
.ch_page_ctrl = R_AX_CH_PAGE_CTRL,
@ -185,6 +189,10 @@ static const struct rtw89_dig_regs rtw8851b_dig_regs = {
.seg0_pd_reg = R_SEG0R_PD_V1,
.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
.pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1,
.bmode_pd_reg = R_BMODE_PDTH_EN_V1,
.bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1,
.bmode_pd_lower_bound_reg = R_BMODE_PDTH_V1,
.bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1,
.p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK},
.p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK},
.p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1},
@ -201,6 +209,20 @@ static const struct rtw89_dig_regs rtw8851b_dig_regs = {
B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
};
static const struct rtw89_edcca_regs rtw8851b_edcca_regs = {
.edcca_level = R_SEG0R_EDCCA_LVL_V1,
.edcca_mask = B_EDCCA_LVL_MSK0,
.edcca_p_mask = B_EDCCA_LVL_MSK1,
.ppdu_level = R_SEG0R_EDCCA_LVL_V1,
.ppdu_mask = B_EDCCA_LVL_MSK3,
.rpt_a = R_EDCCA_RPT_A,
.rpt_b = R_EDCCA_RPT_B,
.rpt_sel = R_EDCCA_RPT_SEL,
.rpt_sel_mask = B_EDCCA_RPT_SEL_MSK,
.tx_collision_t2r_st = R_TX_COLLISION_T2R_ST,
.tx_collision_t2r_st_mask = B_TX_COLLISION_T2R_ST_M,
};
static const struct rtw89_btc_rf_trx_para rtw89_btc_8851b_rf_ul[] = {
{255, 0, 0, 7}, /* 0 -> original */
{255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */
@ -496,7 +518,8 @@ static void rtw8851b_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev,
gain->offset_valid = valid;
}
static int rtw8851b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map)
static int rtw8851b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
enum rtw89_efuse_block block)
{
struct rtw89_efuse *efuse = &rtwdev->efuse;
struct rtw8851b_efuse *map;
@ -756,9 +779,9 @@ static void rtw8851b_set_channel_mac(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
u8 mac_idx)
{
u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, mac_idx);
u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx);
u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx);
u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx);
u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXRATE_CHK, mac_idx);
u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_AX_WMAC_RFMOD, mac_idx);
u8 txsc20 = 0, txsc40 = 0;
switch (chan->band_width) {
@ -882,7 +905,7 @@ static void rtw8851b_set_gain_error(struct rtw89_dev *rtwdev,
enum rtw89_subband subband,
enum rtw89_rf_path path)
{
const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain;
const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
u8 gain_band = rtw89_subband_to_bb_gain_band(subband);
s32 val;
u32 reg;
@ -968,7 +991,7 @@ static void rtw8851b_set_gain_offset(struct rtw89_dev *rtwdev,
static
void rtw8851b_set_rxsc_rpl_comp(struct rtw89_dev *rtwdev, enum rtw89_subband subband)
{
const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain;
const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
u8 band = rtw89_subband_to_bb_gain_band(subband);
u32 val;
@ -1700,10 +1723,11 @@ static void rtw8851b_set_tx_shape(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
{
const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
u8 band = chan->band_type;
u8 regd = rtw89_regd_get(rtwdev, band);
u8 tx_shape_cck = rtw89_8851b_tx_shape[band][RTW89_RS_CCK][regd];
u8 tx_shape_ofdm = rtw89_8851b_tx_shape[band][RTW89_RS_OFDM][regd];
u8 tx_shape_cck = (*rfe_parms->tx_shape.lmt)[band][RTW89_RS_CCK][regd];
u8 tx_shape_ofdm = (*rfe_parms->tx_shape.lmt)[band][RTW89_RS_OFDM][regd];
if (band == RTW89_BAND_2G)
rtw8851b_bb_set_tx_shape_dfir(rtwdev, chan, tx_shape_cck, phy_idx);
@ -1740,14 +1764,14 @@ void rtw8851b_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
return;
}
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_CTRL, mac_idx);
rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN);
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, pw_ofst);
pw_ofst = max_t(s8, pw_ofst - 3, -16);
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_MASK, pw_ofst);
}
@ -1774,14 +1798,15 @@ rtw8851b_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
return 0;
}
static void rtw8851b_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en)
static void rtw8851b_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
rtw89_phy_write_reg3_tbl(rtwdev, bt_en ? &rtw8851b_btc_preagc_en_defs_tbl :
rtw89_phy_write_reg3_tbl(rtwdev, en ? &rtw8851b_btc_preagc_en_defs_tbl :
&rtw8851b_btc_preagc_dis_defs_tbl);
if (!bt_en) {
if (!en) {
if (chan->band_type == RTW89_BAND_2G) {
rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
B_PATH0_G_LNA6_OP1DB_V1, 0x20);
@ -1796,11 +1821,12 @@ static void rtw8851b_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en)
}
}
static void rtw8851b_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
static void rtw8851b_ctrl_btg_bt_rx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
if (btg) {
if (en) {
rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1,
B_PATH0_BT_SHARE_V1, 0x1);
rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1,
@ -1899,41 +1925,81 @@ static u8 rtw8851b_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_p
static void rtw8851b_btc_set_rfe(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_module *module = &btc->mdinfo;
const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
module->rfe_type = rtwdev->efuse.rfe_type;
module->cv = rtwdev->hal.cv;
module->bt_solo = 0;
module->switch_type = BTC_SWITCH_INTERNAL;
module->ant.isolation = 10;
module->kt_ver_adie = rtwdev->hal.acv;
if (ver->fcxinit == 7) {
md->md_v7.rfe_type = rtwdev->efuse.rfe_type;
md->md_v7.kt_ver = rtwdev->hal.cv;
md->md_v7.bt_solo = 0;
md->md_v7.switch_type = BTC_SWITCH_INTERNAL;
md->md_v7.ant.isolation = 10;
md->md_v7.kt_ver_adie = rtwdev->hal.acv;
if (module->rfe_type == 0)
return;
if (md->md_v7.rfe_type == 0)
return;
/* rfe_type 3*n+1: 1-Ant(shared),
* 3*n+2: 2-Ant+Div(non-shared),
* 3*n+3: 2-Ant+no-Div(non-shared)
*/
module->ant.num = (module->rfe_type % 3 == 1) ? 1 : 2;
/* WL-1ss at S0, btg at s0 (On 1 WL RF) */
module->ant.single_pos = RF_PATH_A;
module->ant.btg_pos = RF_PATH_A;
module->ant.stream_cnt = 1;
/* rfe_type 3*n+1: 1-Ant(shared),
* 3*n+2: 2-Ant+Div(non-shared),
* 3*n+3: 2-Ant+no-Div(non-shared)
*/
md->md_v7.ant.num = (md->md_v7.rfe_type % 3 == 1) ? 1 : 2;
/* WL-1ss at S0, btg at s0 (On 1 WL RF) */
md->md_v7.ant.single_pos = RF_PATH_A;
md->md_v7.ant.btg_pos = RF_PATH_A;
md->md_v7.ant.stream_cnt = 1;
if (module->ant.num == 1) {
module->ant.type = BTC_ANT_SHARED;
module->bt_pos = BTC_BT_BTG;
module->wa_type = 1;
module->ant.diversity = 0;
} else { /* ant.num == 2 */
module->ant.type = BTC_ANT_DEDICATED;
module->bt_pos = BTC_BT_ALONE;
module->switch_type = BTC_SWITCH_EXTERNAL;
module->wa_type = 0;
if (module->rfe_type % 3 == 2)
module->ant.diversity = 1;
if (md->md_v7.ant.num == 1) {
md->md_v7.ant.type = BTC_ANT_SHARED;
md->md_v7.bt_pos = BTC_BT_BTG;
md->md_v7.wa_type = 1;
md->md_v7.ant.diversity = 0;
} else { /* ant.num == 2 */
md->md_v7.ant.type = BTC_ANT_DEDICATED;
md->md_v7.bt_pos = BTC_BT_ALONE;
md->md_v7.switch_type = BTC_SWITCH_EXTERNAL;
md->md_v7.wa_type = 0;
if (md->md_v7.rfe_type % 3 == 2)
md->md_v7.ant.diversity = 1;
}
rtwdev->btc.btg_pos = md->md_v7.ant.btg_pos;
rtwdev->btc.ant_type = md->md_v7.ant.type;
} else {
md->md.rfe_type = rtwdev->efuse.rfe_type;
md->md.cv = rtwdev->hal.cv;
md->md.bt_solo = 0;
md->md.switch_type = BTC_SWITCH_INTERNAL;
md->md.ant.isolation = 10;
md->md.kt_ver_adie = rtwdev->hal.acv;
if (md->md.rfe_type == 0)
return;
/* rfe_type 3*n+1: 1-Ant(shared),
* 3*n+2: 2-Ant+Div(non-shared),
* 3*n+3: 2-Ant+no-Div(non-shared)
*/
md->md.ant.num = (md->md.rfe_type % 3 == 1) ? 1 : 2;
/* WL-1ss at S0, btg at s0 (On 1 WL RF) */
md->md.ant.single_pos = RF_PATH_A;
md->md.ant.btg_pos = RF_PATH_A;
md->md.ant.stream_cnt = 1;
if (md->md.ant.num == 1) {
md->md.ant.type = BTC_ANT_SHARED;
md->md.bt_pos = BTC_BT_BTG;
md->md.wa_type = 1;
md->md.ant.diversity = 0;
} else { /* ant.num == 2 */
md->md.ant.type = BTC_ANT_DEDICATED;
md->md.bt_pos = BTC_BT_ALONE;
md->md.switch_type = BTC_SWITCH_EXTERNAL;
md->md.wa_type = 0;
if (md->md.rfe_type % 3 == 2)
md->md.ant.diversity = 1;
}
rtwdev->btc.btg_pos = md->md.ant.btg_pos;
rtwdev->btc.ant_type = md->md.ant.type;
}
}
@ -1943,7 +2009,7 @@ void rtw8851b_set_trx_mask(struct rtw89_dev *rtwdev, u8 path, u8 group, u32 val)
if (group > BTC_BT_SS_GROUP)
group--; /* Tx-group=1, Rx-group=2 */
if (rtwdev->btc.mdinfo.ant.type == BTC_ANT_SHARED) /* 1-Ant */
if (rtwdev->btc.ant_type == BTC_ANT_SHARED) /* 1-Ant */
group += 3;
rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, group);
@ -1958,9 +2024,9 @@ static void rtw8851b_btc_init_cfg(struct rtw89_dev *rtwdev)
};
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_module *module = &btc->mdinfo;
struct rtw89_btc_ant_info *ant = &module->ant;
u8 path, path_min, path_max;
union rtw89_btc_module_info *md = &btc->mdinfo;
const struct rtw89_btc_ver *ver = btc->ver;
u8 path, path_min, path_max, str_cnt, ant_sing_pos;
/* PTA init */
rtw89_mac_coex_init(rtwdev, &coex_params);
@ -1969,9 +2035,17 @@ static void rtw8851b_btc_init_cfg(struct rtw89_dev *rtwdev)
chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_TX_RESP, true);
chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_BEACON, true);
if (ver->fcxinit == 7) {
str_cnt = md->md_v7.ant.stream_cnt;
ant_sing_pos = md->md_v7.ant.single_pos;
} else {
str_cnt = md->md.ant.stream_cnt;
ant_sing_pos = md->md.ant.single_pos;
}
/* for 1-Ant && 1-ss case: only 1-path */
if (ant->stream_cnt == 1) {
path_min = ant->single_pos;
if (str_cnt == 1) {
path_min = ant_sing_pos;
path_max = path_min;
} else {
path_min = RF_PATH_A;
@ -1994,7 +2068,7 @@ static void rtw8851b_btc_init_cfg(struct rtw89_dev *rtwdev)
/* if GNT_WL = 0 && BT = Tx_group -->
* Shared-Ant && BTG-path:WL mask(0x55f), others:WL THRU(0x5ff)
*/
if (ant->type == BTC_ANT_SHARED && ant->btg_pos == path)
if (btc->ant_type == BTC_ANT_SHARED && btc->btg_pos == path)
rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x55f);
else
rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x5ff);
@ -2126,19 +2200,18 @@ void rtw8851b_btc_update_bt_cnt(struct rtw89_dev *rtwdev)
static void rtw8851b_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant;
rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x80000);
rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWA, RFREG_MASK, 0x1);
rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD1, RFREG_MASK, 0x110);
rtw89_write_rf(rtwdev, btc->btg_pos, RR_LUTWE, RFREG_MASK, 0x80000);
rtw89_write_rf(rtwdev, btc->btg_pos, RR_LUTWA, RFREG_MASK, 0x1);
rtw89_write_rf(rtwdev, btc->btg_pos, RR_LUTWD1, RFREG_MASK, 0x110);
/* set WL standby = Rx for GNT_BT_Tx = 1->0 settle issue */
if (state)
rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x179c);
rtw89_write_rf(rtwdev, btc->btg_pos, RR_LUTWD0, RFREG_MASK, 0x179c);
else
rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x208);
rtw89_write_rf(rtwdev, btc->btg_pos, RR_LUTWD0, RFREG_MASK, 0x208);
rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x0);
rtw89_write_rf(rtwdev, btc->btg_pos, RR_LUTWE, RFREG_MASK, 0x0);
}
#define LNA2_51B_MA 0x700
@ -2153,7 +2226,6 @@ static void rtw8851b_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
* level=1 Fix LNA2=5: TIA 1/0= (LNA2,TIAN6) = (5,0)/(5,1) = 18dB/12dB
*/
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant;
const struct rtw89_reg2_def *rf;
u32 n, i, val;
@ -2181,10 +2253,10 @@ static void rtw8851b_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
for (i = 0; i < n; i++, rf++) {
val = rf->data;
/* bit[10] = 1 if non-shared-ant for 8851b */
if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED)
if (btc->ant_type == BTC_ANT_DEDICATED)
val |= 0x4;
rtw89_write_rf(rtwdev, ant->btg_pos, rf->addr, LNA2_51B_MA, val);
rtw89_write_rf(rtwdev, btc->btg_pos, rf->addr, LNA2_51B_MA, val);
}
}
@ -2252,6 +2324,7 @@ static int rtw8851b_mac_disable_bb_rf(struct rtw89_dev *rtwdev)
u8 wl_rfc_s1;
int ret;
rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN,
B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN);
@ -2276,6 +2349,8 @@ static int rtw8851b_mac_disable_bb_rf(struct rtw89_dev *rtwdev)
static const struct rtw89_chip_ops rtw8851b_chip_ops = {
.enable_bb_rf = rtw8851b_mac_enable_bb_rf,
.disable_bb_rf = rtw8851b_mac_disable_bb_rf,
.bb_preinit = NULL,
.bb_postinit = NULL,
.bb_reset = rtw8851b_bb_reset,
.bb_sethw = rtw8851b_bb_sethw,
.read_rf = rtw89_phy_read_rf_v1,
@ -2286,7 +2361,9 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
.read_phycap = rtw8851b_read_phycap,
.fem_setup = NULL,
.rfe_gpio = rtw8851b_rfe_gpio,
.rfk_hw_init = NULL,
.rfk_init = rtw8851b_rfk_init,
.rfk_init_late = NULL,
.rfk_channel = rtw8851b_rfk_channel,
.rfk_band_changed = rtw8851b_rfk_band_changed,
.rfk_scan = rtw8851b_rfk_scan,
@ -2296,9 +2373,9 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
.set_txpwr_ctrl = rtw8851b_set_txpwr_ctrl,
.init_txpwr_unit = rtw8851b_init_txpwr_unit,
.get_thermal = rtw8851b_get_thermal,
.ctrl_btg = rtw8851b_ctrl_btg,
.ctrl_btg_bt_rx = rtw8851b_ctrl_btg_bt_rx,
.query_ppdu = rtw8851b_query_ppdu,
.bb_ctrl_btc_preagc = rtw8851b_bb_ctrl_btc_preagc,
.ctrl_nbtg_bt_tx = rtw8851b_ctrl_nbtg_bt_tx,
.cfg_txrx_path = rtw8851b_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8851b_set_txpwr_ul_tb_offset,
.pwr_on_func = rtw8851b_pwr_on_func,
@ -2311,6 +2388,12 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
.stop_sch_tx = rtw89_mac_stop_sch_tx,
.resume_sch_tx = rtw89_mac_resume_sch_tx,
.h2c_dctl_sec_cam = NULL,
.h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl,
.h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl,
.h2c_ampdu_cmac_tbl = NULL,
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
.btc_set_rfe = rtw8851b_btc_set_rfe,
.btc_init_cfg = rtw8851b_btc_init_cfg,
@ -2336,9 +2419,12 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.chip_id = RTL8851B,
.chip_gen = RTW89_CHIP_AX,
.ops = &rtw8851b_chip_ops,
.mac_def = &rtw89_mac_gen_ax,
.phy_def = &rtw89_phy_gen_ax,
.fw_basename = RTW8851B_FW_BASENAME,
.fw_format_max = RTW8851B_FW_FORMAT_MAX,
.try_ce_fw = true,
.bbmcu_nr = 0,
.needed_fw_elms = 0,
.fifo_size = 196608,
.small_fifo_size = true,
@ -2348,8 +2434,8 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.rsvd_ple_ofst = 0x2f800,
.hfc_param_ini = rtw8851b_hfc_param_ini_pcie,
.dle_mem = rtw8851b_dle_mem_pcie,
.wde_qempty_acq_num = 4,
.wde_qempty_mgq_sel = 4,
.wde_qempty_acq_grpnum = 4,
.wde_qempty_mgq_grpsel = 4,
.rf_base_addr = {0xe000},
.pwr_on_seq = NULL,
.pwr_off_seq = NULL,
@ -2358,7 +2444,6 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.rf_table = {&rtw89_8851b_phy_radioa_table,},
.nctl_table = &rtw89_8851b_phy_nctl_table,
.nctl_post_table = &rtw8851b_nctl_post_defs_tbl,
.byr_table = &rtw89_8851b_byr_table,
.dflt_parms = &rtw89_8851b_dflt_parms,
.rfe_parms_conf = rtw89_8851b_rfe_parms_conf,
.txpwr_factor_rf = 2,
@ -2366,12 +2451,17 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.dig_table = NULL,
.dig_regs = &rtw8851b_dig_regs,
.tssi_dbw_table = NULL,
.support_macid_num = RTW89_MAX_MAC_ID_NUM,
.support_chanctx_num = 0,
.support_rnr = false,
.support_bands = BIT(NL80211_BAND_2GHZ) |
BIT(NL80211_BAND_5GHZ),
.support_bw160 = false,
.support_bandwidths = BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = true,
.support_ul_tb_ctrl = true,
.ul_tb_waveform_ctrl = true,
.ul_tb_pwr_diff = false,
.hw_sec_hdr = false,
.rf_path_num = 1,
.tx_nss = 1,
@ -2382,12 +2472,14 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.bacam_num = 2,
.bacam_dynamic_num = 4,
.bacam_ver = RTW89_BACAM_V0,
.ppdu_max_usr = 4,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 2048,
.limit_efuse_size = 1280,
.dav_phy_efuse_size = 0,
.dav_log_efuse_size = 0,
.efuse_blocks = NULL,
.phycap_addr = 0x580,
.phycap_size = 128,
.para_ver = 0,
@ -2413,6 +2505,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.hci_func_en_addr = R_AX_HCI_FUNC_EN,
.h2c_desc_size = sizeof(struct rtw89_txwd_body),
.txwd_body_size = sizeof(struct rtw89_txwd_body),
.txwd_info_size = sizeof(struct rtw89_txwd_info),
.h2c_ctrl_reg = R_AX_H2CREG_CTRL,
.h2c_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_H2C_DEQ_CNT_MASK >> 8},
.h2c_regs = rtw8851b_h2c_regs,
@ -2420,17 +2513,21 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8},
.c2h_regs = rtw8851b_c2h_regs,
.page_regs = &rtw8851b_page_regs,
.wow_reason_reg = rtw8851b_wow_wakeup_regs,
.cfo_src_fd = true,
.cfo_hw_comp = true,
.dcfo_comp = &rtw8851b_dcfo_comp,
.dcfo_comp_sft = 12,
.imr_info = &rtw8851b_imr_info,
.imr_dmac_table = NULL,
.imr_cmac_table = NULL,
.rrsr_cfgs = &rtw8851b_rrsr_cfgs,
.bss_clr_vld = {R_BSS_CLR_MAP_V1, B_BSS_CLR_MAP_VLD0},
.bss_clr_map_reg = R_BSS_CLR_MAP_V1,
.dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
.edcca_lvl_reg = R_SEG0R_EDCCA_LVL_V1,
.edcca_regs = &rtw8851b_edcca_regs,
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8851b,
#endif

File diff suppressed because it is too large Load Diff

View File

@ -11,10 +11,7 @@ extern const struct rtw89_phy_table rtw89_8851b_phy_bb_table;
extern const struct rtw89_phy_table rtw89_8851b_phy_bb_gain_table;
extern const struct rtw89_phy_table rtw89_8851b_phy_radioa_table;
extern const struct rtw89_phy_table rtw89_8851b_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8851b_byr_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8851b_trk_cfg;
extern const u8 rtw89_8851b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
extern const struct rtw89_rfe_parms rtw89_8851b_dflt_parms;
extern const struct rtw89_rfe_parms_conf rtw89_8851b_rfe_parms_conf[];

View File

@ -10,6 +10,7 @@
#include "rtw8851b.h"
static const struct rtw89_pci_info rtw8851b_pci_info = {
.gen_def = &rtw89_pci_gen_ax,
.txbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_mode = MAC_AX_RXBD_PKT,
@ -24,6 +25,8 @@ static const struct rtw89_pci_info rtw8851b_pci_info = {
.autok_en = MAC_AX_PCIE_DISABLE,
.io_rcy_en = MAC_AX_PCIE_DISABLE,
.io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
.rx_ring_eq_is_full = false,
.check_rx_tag = false,
.init_cfg_reg = R_AX_PCIE_INIT_CFG1,
.txhci_en_bit = B_AX_TXHCI_EN,
@ -33,6 +36,7 @@ static const struct rtw89_pci_info rtw8851b_pci_info = {
.max_tag_num_mask = B_AX_MAX_TAG_NUM,
.rxbd_rwptr_clr_reg = R_AX_RXBD_RWPTR_CLR,
.txbd_rwptr_clr2_reg = 0,
.dma_io_stop = {R_AX_PCIE_DMA_STOP1, B_AX_STOP_PCIEIO},
.dma_stop1 = {R_AX_PCIE_DMA_STOP1, B_AX_TX_STOP1_MASK_V1},
.dma_stop2 = {0},
.dma_busy1 = {R_AX_PCIE_DMA_BUSY1, DMA_BUSY1_CHECK_V1},
@ -41,6 +45,8 @@ static const struct rtw89_pci_info rtw8851b_pci_info = {
.rpwm_addr = R_AX_PCIE_HRPWM,
.cpwm_addr = R_AX_CPWM,
.mit_addr = R_AX_INT_MIT_RX,
.wp_sel_addr = 0,
.tx_dma_ch_mask = BIT(RTW89_TXCH_ACH4) | BIT(RTW89_TXCH_ACH5) |
BIT(RTW89_TXCH_ACH6) | BIT(RTW89_TXCH_ACH7) |
BIT(RTW89_TXCH_CH10) | BIT(RTW89_TXCH_CH11),
@ -58,6 +64,7 @@ static const struct rtw89_pci_info rtw8851b_pci_info = {
static const struct rtw89_driver_info rtw89_8851be_info = {
.chip = &rtw8851b_chip_info,
.quirks = NULL,
.bus = {
.pci = &rtw8851b_pci_info,
},

View File

@ -398,6 +398,10 @@ static const u32 rtw8852a_c2h_regs[RTW89_C2HREG_MAX] = {
R_AX_C2HREG_DATA3
};
static const u32 rtw8852a_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = {
R_AX_C2HREG_DATA3 + 3, R_AX_C2HREG_DATA3 + 3,
};
static const struct rtw89_page_regs rtw8852a_page_regs = {
.hci_fc_ctrl = R_AX_HCI_FC_CTRL,
.ch_page_ctrl = R_AX_CH_PAGE_CTRL,
@ -478,6 +482,10 @@ static const struct rtw89_dig_regs rtw8852a_dig_regs = {
.seg0_pd_reg = R_SEG0R_PD,
.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
.pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK,
.bmode_pd_reg = R_BMODE_PDTH_EN_V1,
.bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1,
.bmode_pd_lower_bound_reg = R_BMODE_PDTH_V1,
.bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1,
.p0_lna_init = {R_PATH0_LNA_INIT, B_PATH0_LNA_INIT_IDX_MSK},
.p1_lna_init = {R_PATH1_LNA_INIT, B_PATH1_LNA_INIT_IDX_MSK},
.p0_tia_init = {R_PATH0_TIA_INIT, B_PATH0_TIA_INIT_IDX_MSK},
@ -494,6 +502,20 @@ static const struct rtw89_dig_regs rtw8852a_dig_regs = {
B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
};
static const struct rtw89_edcca_regs rtw8852a_edcca_regs = {
.edcca_level = R_SEG0R_EDCCA_LVL,
.edcca_mask = B_EDCCA_LVL_MSK0,
.edcca_p_mask = B_EDCCA_LVL_MSK1,
.ppdu_level = R_SEG0R_EDCCA_LVL,
.ppdu_mask = B_EDCCA_LVL_MSK3,
.rpt_a = R_EDCCA_RPT_A,
.rpt_b = R_EDCCA_RPT_B,
.rpt_sel = R_EDCCA_RPT_SEL,
.rpt_sel_mask = B_EDCCA_RPT_SEL_MSK,
.tx_collision_t2r_st = R_TX_COLLISION_T2R_ST,
.tx_collision_t2r_st_mask = B_TX_COLLISION_T2R_ST_M,
};
static void rtw8852ae_efuse_parsing(struct rtw89_efuse *efuse,
struct rtw8852a_efuse *map)
{
@ -533,7 +555,8 @@ static void rtw8852a_efuse_parsing_tssi(struct rtw89_dev *rtwdev,
}
}
static int rtw8852a_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map)
static int rtw8852a_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
enum rtw89_efuse_block block)
{
struct rtw89_efuse *efuse = &rtwdev->efuse;
struct rtw8852a_efuse *map;
@ -704,10 +727,9 @@ static void rtw8852a_set_channel_mac(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
u8 mac_idx)
{
u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx);
u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE,
mac_idx);
u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx);
u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_AX_WMAC_RFMOD, mac_idx);
u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx);
u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXRATE_CHK, mac_idx);
u8 txsc20 = 0, txsc40 = 0;
switch (chan->band_width) {
@ -1380,13 +1402,13 @@ void rtw8852a_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
pw_ofst);
return;
}
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_CTRL, mac_idx);
rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN);
val_1t = pw_ofst;
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, val_1t);
val_2t = max(val_1t - 3, -16);
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_MASK, val_2t);
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[ULTB] Set TB pwr_offset=(%d, %d)\n",
val_1t, val_2t);
@ -1621,9 +1643,10 @@ void rtw8852a_bb_tx_mode_switch(struct rtw89_dev *rtwdev,
rtw89_phy_write32_idx(rtwdev, R_MAC_SEL, B_MAC_SEL_PWR_EN, 0, idx);
}
static void rtw8852a_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en)
static void rtw8852a_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
rtw89_phy_write_reg3_tbl(rtwdev, bt_en ? &rtw8852a_btc_preagc_en_defs_tbl :
rtw89_phy_write_reg3_tbl(rtwdev, en ? &rtw8852a_btc_preagc_en_defs_tbl :
&rtw8852a_btc_preagc_dis_defs_tbl);
}
@ -1646,28 +1669,55 @@ static u8 rtw8852a_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_p
static void rtw8852a_btc_set_rfe(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_module *module = &btc->mdinfo;
const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
module->rfe_type = rtwdev->efuse.rfe_type;
module->cv = rtwdev->hal.cv;
module->bt_solo = 0;
module->switch_type = BTC_SWITCH_INTERNAL;
if (ver->fcxinit == 7) {
md->md_v7.rfe_type = rtwdev->efuse.rfe_type;
md->md_v7.kt_ver = rtwdev->hal.cv;
md->md_v7.bt_solo = 0;
md->md_v7.switch_type = BTC_SWITCH_INTERNAL;
if (module->rfe_type > 0)
module->ant.num = (module->rfe_type % 2 ? 2 : 3);
else
module->ant.num = 2;
if (md->md_v7.rfe_type > 0)
md->md_v7.ant.num = (md->md_v7.rfe_type % 2 ? 2 : 3);
else
md->md_v7.ant.num = 2;
module->ant.diversity = 0;
module->ant.isolation = 10;
md->md_v7.ant.diversity = 0;
md->md_v7.ant.isolation = 10;
if (module->ant.num == 3) {
module->ant.type = BTC_ANT_DEDICATED;
module->bt_pos = BTC_BT_ALONE;
if (md->md_v7.ant.num == 3) {
md->md_v7.ant.type = BTC_ANT_DEDICATED;
md->md_v7.bt_pos = BTC_BT_ALONE;
} else {
md->md_v7.ant.type = BTC_ANT_SHARED;
md->md_v7.bt_pos = BTC_BT_BTG;
}
rtwdev->btc.btg_pos = md->md_v7.ant.btg_pos;
rtwdev->btc.ant_type = md->md_v7.ant.type;
} else {
module->ant.type = BTC_ANT_SHARED;
module->bt_pos = BTC_BT_BTG;
md->md.rfe_type = rtwdev->efuse.rfe_type;
md->md.cv = rtwdev->hal.cv;
md->md.bt_solo = 0;
md->md.switch_type = BTC_SWITCH_INTERNAL;
if (md->md.rfe_type > 0)
md->md.ant.num = (md->md.rfe_type % 2 ? 2 : 3);
else
md->md.ant.num = 2;
md->md.ant.diversity = 0;
md->md.ant.isolation = 10;
if (md->md.ant.num == 3) {
md->md.ant.type = BTC_ANT_DEDICATED;
md->md.bt_pos = BTC_BT_ALONE;
} else {
md->md.ant.type = BTC_ANT_SHARED;
md->md.bt_pos = BTC_BT_BTG;
}
rtwdev->btc.btg_pos = md->md.ant.btg_pos;
rtwdev->btc.ant_type = md->md.ant.type;
}
}
@ -1680,9 +1730,10 @@ void rtw8852a_set_trx_mask(struct rtw89_dev *rtwdev, u8 path, u8 group, u32 val)
rtw89_write_rf(rtwdev, path, RR_LUTWE, 0xfffff, 0x0);
}
static void rtw8852a_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
static void rtw8852a_ctrl_btg_bt_rx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
if (btg) {
if (en) {
rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG, B_PATH0_BTG_SHEN, 0x1);
rtw89_phy_write32_mask(rtwdev, R_PATH1_BTG, B_PATH1_BTG_SHEN, 0x3);
rtw89_phy_write32_mask(rtwdev, R_PMAC_GNT, B_PMAC_GNT_P1, 0x0);
@ -1697,7 +1748,6 @@ static void rtw8852a_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
static void rtw8852a_btc_init_cfg(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_module *module = &btc->mdinfo;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_mac_ax_coex coex_params = {
.pta_mode = RTW89_MAC_AX_COEX_RTK_MODE,
@ -1716,7 +1766,7 @@ static void rtw8852a_btc_init_cfg(struct rtw89_dev *rtwdev)
rtw89_write_rf(rtwdev, RF_PATH_B, RR_WLSEL, 0xfffff, 0x0);
/* set WL Tx thru in TRX mask table if GNT_WL = 0 && BT_S1 = ss group */
if (module->ant.type == BTC_ANT_SHARED) {
if (btc->ant_type == BTC_ANT_SHARED) {
rtw8852a_set_trx_mask(rtwdev,
RF_PATH_A, BTC_BT_SS_GROUP, 0x5ff);
rtw8852a_set_trx_mask(rtwdev,
@ -1963,15 +2013,15 @@ static void rtw8852a_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
switch (level) {
case 0: /* original */
default:
rtw8852a_bb_ctrl_btc_preagc(rtwdev, false);
rtw8852a_ctrl_nbtg_bt_tx(rtwdev, false, RTW89_PHY_0);
btc->dm.wl_lna2 = 0;
break;
case 1: /* for FDD free-run */
rtw8852a_bb_ctrl_btc_preagc(rtwdev, true);
rtw8852a_ctrl_nbtg_bt_tx(rtwdev, true, RTW89_PHY_0);
btc->dm.wl_lna2 = 0;
break;
case 2: /* for BTG Co-Rx*/
rtw8852a_bb_ctrl_btc_preagc(rtwdev, false);
rtw8852a_ctrl_nbtg_bt_tx(rtwdev, false, RTW89_PHY_0);
btc->dm.wl_lna2 = 1;
break;
}
@ -2022,6 +2072,8 @@ static const struct wiphy_wowlan_support rtw_wowlan_stub_8852a = {
static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.enable_bb_rf = rtw89_mac_enable_bb_rf,
.disable_bb_rf = rtw89_mac_disable_bb_rf,
.bb_preinit = NULL,
.bb_postinit = NULL,
.bb_reset = rtw8852a_bb_reset,
.bb_sethw = rtw8852a_bb_sethw,
.read_rf = rtw89_phy_read_rf,
@ -2032,7 +2084,9 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.read_phycap = rtw8852a_read_phycap,
.fem_setup = rtw8852a_fem_setup,
.rfe_gpio = NULL,
.rfk_hw_init = NULL,
.rfk_init = rtw8852a_rfk_init,
.rfk_init_late = NULL,
.rfk_channel = rtw8852a_rfk_channel,
.rfk_band_changed = rtw8852a_rfk_band_changed,
.rfk_scan = rtw8852a_rfk_scan,
@ -2042,9 +2096,9 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.set_txpwr_ctrl = rtw8852a_set_txpwr_ctrl,
.init_txpwr_unit = rtw8852a_init_txpwr_unit,
.get_thermal = rtw8852a_get_thermal,
.ctrl_btg = rtw8852a_ctrl_btg,
.ctrl_btg_bt_rx = rtw8852a_ctrl_btg_bt_rx,
.query_ppdu = rtw8852a_query_ppdu,
.bb_ctrl_btc_preagc = rtw8852a_bb_ctrl_btc_preagc,
.ctrl_nbtg_bt_tx = rtw8852a_ctrl_nbtg_bt_tx,
.cfg_txrx_path = NULL,
.set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset,
.pwr_on_func = NULL,
@ -2057,6 +2111,12 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.stop_sch_tx = rtw89_mac_stop_sch_tx,
.resume_sch_tx = rtw89_mac_resume_sch_tx,
.h2c_dctl_sec_cam = NULL,
.h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl,
.h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl,
.h2c_ampdu_cmac_tbl = NULL,
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
.btc_set_rfe = rtw8852a_btc_set_rfe,
.btc_init_cfg = rtw8852a_btc_init_cfg,
@ -2073,9 +2133,12 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.chip_id = RTL8852A,
.chip_gen = RTW89_CHIP_AX,
.ops = &rtw8852a_chip_ops,
.mac_def = &rtw89_mac_gen_ax,
.phy_def = &rtw89_phy_gen_ax,
.fw_basename = RTW8852A_FW_BASENAME,
.fw_format_max = RTW8852A_FW_FORMAT_MAX,
.try_ce_fw = false,
.bbmcu_nr = 0,
.needed_fw_elms = 0,
.fifo_size = 458752,
.small_fifo_size = false,
@ -2085,8 +2148,8 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.rsvd_ple_ofst = 0x6f800,
.hfc_param_ini = rtw8852a_hfc_param_ini_pcie,
.dle_mem = rtw8852a_dle_mem_pcie,
.wde_qempty_acq_num = 16,
.wde_qempty_mgq_sel = 16,
.wde_qempty_acq_grpnum = 16,
.wde_qempty_mgq_grpsel = 16,
.rf_base_addr = {0xc000, 0xd000},
.pwr_on_seq = pwr_on_seq_8852a,
.pwr_off_seq = pwr_off_seq_8852a,
@ -2096,7 +2159,6 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
&rtw89_8852a_phy_radiob_table,},
.nctl_table = &rtw89_8852a_phy_nctl_table,
.nctl_post_table = NULL,
.byr_table = &rtw89_8852a_byr_table,
.dflt_parms = &rtw89_8852a_dflt_parms,
.rfe_parms_conf = NULL,
.txpwr_factor_rf = 2,
@ -2104,12 +2166,17 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.dig_table = &rtw89_8852a_phy_dig_table,
.dig_regs = &rtw8852a_dig_regs,
.tssi_dbw_table = NULL,
.support_macid_num = RTW89_MAX_MAC_ID_NUM,
.support_chanctx_num = 1,
.support_rnr = false,
.support_bands = BIT(NL80211_BAND_2GHZ) |
BIT(NL80211_BAND_5GHZ),
.support_bw160 = false,
.support_bandwidths = BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = false,
.support_ul_tb_ctrl = false,
.ul_tb_waveform_ctrl = false,
.ul_tb_pwr_diff = false,
.hw_sec_hdr = false,
.rf_path_num = 2,
.tx_nss = 2,
@ -2120,12 +2187,14 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.bacam_num = 2,
.bacam_dynamic_num = 4,
.bacam_ver = RTW89_BACAM_V0,
.ppdu_max_usr = 4,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 1536,
.limit_efuse_size = 1152,
.dav_phy_efuse_size = 0,
.dav_log_efuse_size = 0,
.efuse_blocks = NULL,
.phycap_addr = 0x580,
.phycap_size = 128,
.para_ver = 0x0,
@ -2152,6 +2221,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.hci_func_en_addr = R_AX_HCI_FUNC_EN,
.h2c_desc_size = sizeof(struct rtw89_txwd_body),
.txwd_body_size = sizeof(struct rtw89_txwd_body),
.txwd_info_size = sizeof(struct rtw89_txwd_info),
.h2c_ctrl_reg = R_AX_H2CREG_CTRL,
.h2c_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_H2C_DEQ_CNT_MASK >> 8},
.h2c_regs = rtw8852a_h2c_regs,
@ -2159,15 +2229,19 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.c2h_regs = rtw8852a_c2h_regs,
.c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8},
.page_regs = &rtw8852a_page_regs,
.wow_reason_reg = rtw8852a_wow_wakeup_regs,
.cfo_src_fd = false,
.cfo_hw_comp = false,
.dcfo_comp = &rtw8852a_dcfo_comp,
.dcfo_comp_sft = 10,
.imr_info = &rtw8852a_imr_info,
.imr_dmac_table = NULL,
.imr_cmac_table = NULL,
.rrsr_cfgs = &rtw8852a_rrsr_cfgs,
.bss_clr_vld = {R_BSS_CLR_MAP, B_BSS_CLR_MAP_VLD0},
.bss_clr_map_reg = R_BSS_CLR_MAP,
.dma_ch_mask = 0,
.edcca_lvl_reg = R_SEG0R_EDCCA_LVL,
.edcca_regs = &rtw8852a_edcca_regs,
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852a,
#endif

View File

@ -51020,6 +51020,7 @@ const struct rtw89_phy_table rtw89_8852a_phy_nctl_table = {
.rf_path = 0, /* don't care */
};
static
const struct rtw89_txpwr_table rtw89_8852a_byr_table = {
.data = rtw89_8852a_txpwr_byrate,
.size = ARRAY_SIZE(rtw89_8852a_txpwr_byrate),
@ -51049,6 +51050,7 @@ const struct rtw89_phy_dig_gain_table rtw89_8852a_phy_dig_table = {
};
const struct rtw89_rfe_parms rtw89_8852a_dflt_parms = {
.byr_tbl = &rtw89_8852a_byr_table,
.rule_2ghz = {
.lmt = &rtw89_8852a_txpwr_lmt_2g,
.lmt_ru = &rtw89_8852a_txpwr_lmt_ru_2g,

View File

@ -11,7 +11,6 @@ extern const struct rtw89_phy_table rtw89_8852a_phy_bb_table;
extern const struct rtw89_phy_table rtw89_8852a_phy_radioa_table;
extern const struct rtw89_phy_table rtw89_8852a_phy_radiob_table;
extern const struct rtw89_phy_table rtw89_8852a_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8852a_byr_table;
extern const struct rtw89_phy_dig_gain_table rtw89_8852a_phy_dig_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852a_trk_cfg;
extern const struct rtw89_rfe_parms rtw89_8852a_dflt_parms;

View File

@ -10,6 +10,7 @@
#include "rtw8852a.h"
static const struct rtw89_pci_info rtw8852a_pci_info = {
.gen_def = &rtw89_pci_gen_ax,
.txbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_mode = MAC_AX_RXBD_PKT,
@ -24,6 +25,8 @@ static const struct rtw89_pci_info rtw8852a_pci_info = {
.autok_en = MAC_AX_PCIE_DISABLE,
.io_rcy_en = MAC_AX_PCIE_DISABLE,
.io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
.rx_ring_eq_is_full = false,
.check_rx_tag = false,
.init_cfg_reg = R_AX_PCIE_INIT_CFG1,
.txhci_en_bit = B_AX_TXHCI_EN,
@ -33,6 +36,7 @@ static const struct rtw89_pci_info rtw8852a_pci_info = {
.max_tag_num_mask = B_AX_MAX_TAG_NUM,
.rxbd_rwptr_clr_reg = R_AX_RXBD_RWPTR_CLR,
.txbd_rwptr_clr2_reg = R_AX_TXBD_RWPTR_CLR2,
.dma_io_stop = {R_AX_PCIE_DMA_STOP1, B_AX_STOP_PCIEIO},
.dma_stop1 = {R_AX_PCIE_DMA_STOP1, B_AX_TX_STOP1_MASK},
.dma_stop2 = {R_AX_PCIE_DMA_STOP2, B_AX_TX_STOP2_ALL},
.dma_busy1 = {R_AX_PCIE_DMA_BUSY1, DMA_BUSY1_CHECK},
@ -41,6 +45,8 @@ static const struct rtw89_pci_info rtw8852a_pci_info = {
.rpwm_addr = R_AX_PCIE_HRPWM,
.cpwm_addr = R_AX_CPWM,
.mit_addr = R_AX_INT_MIT_RX,
.wp_sel_addr = 0,
.tx_dma_ch_mask = 0,
.bd_idx_addr_low_power = NULL,
.dma_addr_set = &rtw89_pci_ch_dma_addr_set,
@ -56,6 +62,7 @@ static const struct rtw89_pci_info rtw8852a_pci_info = {
static const struct rtw89_driver_info rtw89_8852ae_info = {
.chip = &rtw8852a_chip_info,
.quirks = NULL,
.bus = {
.pci = &rtw8852a_pci_info,
},

1988
rtw8852b.c

File diff suppressed because it is too large Load Diff

View File

@ -10,128 +10,6 @@
#define RF_PATH_NUM_8852B 2
#define BB_PATH_NUM_8852B 2
enum rtw8852b_pmac_mode {
NONE_TEST,
PKTS_TX,
PKTS_RX,
CONT_TX
};
struct rtw8852b_u_efuse {
u8 rsvd[0x88];
u8 mac_addr[ETH_ALEN];
};
struct rtw8852b_e_efuse {
u8 mac_addr[ETH_ALEN];
};
struct rtw8852b_tssi_offset {
u8 cck_tssi[TSSI_CCK_CH_GROUP_NUM];
u8 bw40_tssi[TSSI_MCS_2G_CH_GROUP_NUM];
u8 rsvd[7];
u8 bw40_1s_tssi_5g[TSSI_MCS_5G_CH_GROUP_NUM];
} __packed;
struct rtw8852b_efuse {
u8 rsvd[0x210];
struct rtw8852b_tssi_offset path_a_tssi;
u8 rsvd1[10];
struct rtw8852b_tssi_offset path_b_tssi;
u8 rsvd2[94];
u8 channel_plan;
u8 xtal_k;
u8 rsvd3;
u8 iqk_lck;
u8 rsvd4[5];
u8 reg_setting:2;
u8 tx_diversity:1;
u8 rx_diversity:2;
u8 ac_mode:1;
u8 module_type:2;
u8 rsvd5;
u8 shared_ant:1;
u8 coex_type:3;
u8 ant_iso:1;
u8 radio_on_off:1;
u8 rsvd6:2;
u8 eeprom_version;
u8 customer_id;
u8 tx_bb_swing_2g;
u8 tx_bb_swing_5g;
u8 tx_cali_pwr_trk_mode;
u8 trx_path_selection;
u8 rfe_type;
u8 country_code[2];
u8 rsvd7[3];
u8 path_a_therm;
u8 path_b_therm;
u8 rsvd8[2];
u8 rx_gain_2g_ofdm;
u8 rsvd9;
u8 rx_gain_2g_cck;
u8 rsvd10;
u8 rx_gain_5g_low;
u8 rsvd11;
u8 rx_gain_5g_mid;
u8 rsvd12;
u8 rx_gain_5g_high;
u8 rsvd13[35];
u8 path_a_cck_pwr_idx[6];
u8 path_a_bw40_1tx_pwr_idx[5];
u8 path_a_ofdm_1tx_pwr_idx_diff:4;
u8 path_a_bw20_1tx_pwr_idx_diff:4;
u8 path_a_bw20_2tx_pwr_idx_diff:4;
u8 path_a_bw40_2tx_pwr_idx_diff:4;
u8 path_a_cck_2tx_pwr_idx_diff:4;
u8 path_a_ofdm_2tx_pwr_idx_diff:4;
u8 rsvd14[0xf2];
union {
struct rtw8852b_u_efuse u;
struct rtw8852b_e_efuse e;
};
} __packed;
struct rtw8852b_bb_pmac_info {
u8 en_pmac_tx:1;
u8 is_cck:1;
u8 mode:3;
u8 rsvd:3;
u16 tx_cnt;
u16 period;
u16 tx_time;
u8 duty_cycle;
};
struct rtw8852b_bb_tssi_bak {
u8 tx_path;
u8 rx_path;
u32 p0_rfmode;
u32 p0_rfmode_ftm;
u32 p1_rfmode;
u32 p1_rfmode_ftm;
s16 tx_pwr; /* S9 */
};
extern const struct rtw89_chip_info rtw8852b_chip_info;
void rtw8852b_bb_set_plcp_tx(struct rtw89_dev *rtwdev);
void rtw8852b_bb_set_pmac_tx(struct rtw89_dev *rtwdev,
struct rtw8852b_bb_pmac_info *tx_info,
enum rtw89_phy_idx idx);
void rtw8852b_bb_set_pmac_pkt_tx(struct rtw89_dev *rtwdev, u8 enable,
u16 tx_cnt, u16 period, u16 tx_time,
enum rtw89_phy_idx idx);
void rtw8852b_bb_set_power(struct rtw89_dev *rtwdev, s16 pwr_dbm,
enum rtw89_phy_idx idx);
void rtw8852b_bb_cfg_tx_path(struct rtw89_dev *rtwdev, u8 tx_path);
void rtw8852b_bb_ctrl_rx_path(struct rtw89_dev *rtwdev,
enum rtw89_rf_path_bit rx_path);
void rtw8852b_bb_tx_mode_switch(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx idx, u8 mode);
void rtw8852b_bb_backup_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx idx,
struct rtw8852b_bb_tssi_bak *bak);
void rtw8852b_bb_restore_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx idx,
const struct rtw8852b_bb_tssi_bak *bak);
#endif

2053
rtw8852b_common.c Normal file

File diff suppressed because it is too large Load Diff

388
rtw8852b_common.h Normal file
View File

@ -0,0 +1,388 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2024 Realtek Corporation
*/
#ifndef __RTW89_8852BX_H__
#define __RTW89_8852BX_H__
#include "core.h"
#define RF_PATH_NUM_8852BX 2
#define BB_PATH_NUM_8852BX 2
enum rtw8852bx_pmac_mode {
NONE_TEST,
PKTS_TX,
PKTS_RX,
CONT_TX
};
struct rtw8852bx_u_efuse {
u8 rsvd[0x88];
u8 mac_addr[ETH_ALEN];
};
struct rtw8852bx_e_efuse {
u8 mac_addr[ETH_ALEN];
};
struct rtw8852bx_tssi_offset {
u8 cck_tssi[TSSI_CCK_CH_GROUP_NUM];
u8 bw40_tssi[TSSI_MCS_2G_CH_GROUP_NUM];
u8 rsvd[7];
u8 bw40_1s_tssi_5g[TSSI_MCS_5G_CH_GROUP_NUM];
} __packed;
struct rtw8852bx_efuse {
u8 rsvd[0x210];
struct rtw8852bx_tssi_offset path_a_tssi;
u8 rsvd1[10];
struct rtw8852bx_tssi_offset path_b_tssi;
u8 rsvd2[94];
u8 channel_plan;
u8 xtal_k;
u8 rsvd3;
u8 iqk_lck;
u8 rsvd4[5];
u8 reg_setting:2;
u8 tx_diversity:1;
u8 rx_diversity:2;
u8 ac_mode:1;
u8 module_type:2;
u8 rsvd5;
u8 shared_ant:1;
u8 coex_type:3;
u8 ant_iso:1;
u8 radio_on_off:1;
u8 rsvd6:2;
u8 eeprom_version;
u8 customer_id;
u8 tx_bb_swing_2g;
u8 tx_bb_swing_5g;
u8 tx_cali_pwr_trk_mode;
u8 trx_path_selection;
u8 rfe_type;
u8 country_code[2];
u8 rsvd7[3];
u8 path_a_therm;
u8 path_b_therm;
u8 rsvd8[2];
u8 rx_gain_2g_ofdm;
u8 rsvd9;
u8 rx_gain_2g_cck;
u8 rsvd10;
u8 rx_gain_5g_low;
u8 rsvd11;
u8 rx_gain_5g_mid;
u8 rsvd12;
u8 rx_gain_5g_high;
u8 rsvd13[35];
u8 path_a_cck_pwr_idx[6];
u8 path_a_bw40_1tx_pwr_idx[5];
u8 path_a_ofdm_1tx_pwr_idx_diff:4;
u8 path_a_bw20_1tx_pwr_idx_diff:4;
u8 path_a_bw20_2tx_pwr_idx_diff:4;
u8 path_a_bw40_2tx_pwr_idx_diff:4;
u8 path_a_cck_2tx_pwr_idx_diff:4;
u8 path_a_ofdm_2tx_pwr_idx_diff:4;
u8 rsvd14[0xf2];
union {
struct rtw8852bx_u_efuse u;
struct rtw8852bx_e_efuse e;
};
} __packed;
struct rtw8852bx_bb_pmac_info {
u8 en_pmac_tx:1;
u8 is_cck:1;
u8 mode:3;
u8 rsvd:3;
u16 tx_cnt;
u16 period;
u16 tx_time;
u8 duty_cycle;
};
struct rtw8852bx_bb_tssi_bak {
u8 tx_path;
u8 rx_path;
u32 p0_rfmode;
u32 p0_rfmode_ftm;
u32 p1_rfmode;
u32 p1_rfmode_ftm;
s16 tx_pwr; /* S9 */
};
struct rtw8852bx_info {
int (*mac_enable_bb_rf)(struct rtw89_dev *rtwdev);
int (*mac_disable_bb_rf)(struct rtw89_dev *rtwdev);
void (*bb_sethw)(struct rtw89_dev *rtwdev);
void (*bb_reset_all)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void (*bb_cfg_txrx_path)(struct rtw89_dev *rtwdev);
void (*bb_cfg_tx_path)(struct rtw89_dev *rtwdev, u8 tx_path);
void (*bb_ctrl_rx_path)(struct rtw89_dev *rtwdev,
enum rtw89_rf_path_bit rx_path);
void (*bb_set_plcp_tx)(struct rtw89_dev *rtwdev);
void (*bb_set_power)(struct rtw89_dev *rtwdev, s16 pwr_dbm,
enum rtw89_phy_idx idx);
void (*bb_set_pmac_pkt_tx)(struct rtw89_dev *rtwdev, u8 enable,
u16 tx_cnt, u16 period, u16 tx_time,
enum rtw89_phy_idx idx);
void (*bb_backup_tssi)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx idx,
struct rtw8852bx_bb_tssi_bak *bak);
void (*bb_restore_tssi)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx idx,
const struct rtw8852bx_bb_tssi_bak *bak);
void (*bb_tx_mode_switch)(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx idx, u8 mode);
void (*set_channel_mac)(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan, u8 mac_idx);
void (*set_channel_bb)(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
void (*ctrl_nbtg_bt_tx)(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx);
void (*ctrl_btg_bt_rx)(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx);
void (*query_ppdu)(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu,
struct ieee80211_rx_status *status);
int (*read_efuse)(struct rtw89_dev *rtwdev, u8 *log_map,
enum rtw89_efuse_block block);
int (*read_phycap)(struct rtw89_dev *rtwdev, u8 *phycap_map);
void (*power_trim)(struct rtw89_dev *rtwdev);
void (*set_txpwr)(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
void (*set_txpwr_ctrl)(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx);
int (*init_txpwr_unit)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void (*set_txpwr_ul_tb_offset)(struct rtw89_dev *rtwdev,
s8 pw_ofst, enum rtw89_mac_idx mac_idx);
u8 (*get_thermal)(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path);
void (*adc_cfg)(struct rtw89_dev *rtwdev, u8 bw, u8 path);
void (*btc_init_cfg)(struct rtw89_dev *rtwdev);
void (*btc_set_wl_pri)(struct rtw89_dev *rtwdev, u8 map, bool state);
s8 (*btc_get_bt_rssi)(struct rtw89_dev *rtwdev, s8 val);
void (*btc_update_bt_cnt)(struct rtw89_dev *rtwdev);
void (*btc_wl_s1_standby)(struct rtw89_dev *rtwdev, bool state);
void (*btc_set_wl_rx_gain)(struct rtw89_dev *rtwdev, u32 level);
};
extern const struct rtw8852bx_info rtw8852bx_info;
static inline
int rtw8852bx_mac_enable_bb_rf(struct rtw89_dev *rtwdev)
{
return rtw8852bx_info.mac_enable_bb_rf(rtwdev);
}
static inline
int rtw8852bx_mac_disable_bb_rf(struct rtw89_dev *rtwdev)
{
return rtw8852bx_info.mac_disable_bb_rf(rtwdev);
}
static inline
void rtw8852bx_bb_sethw(struct rtw89_dev *rtwdev)
{
rtw8852bx_info.bb_sethw(rtwdev);
}
static inline
void rtw8852bx_bb_reset_all(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
rtw8852bx_info.bb_reset_all(rtwdev, phy_idx);
}
static inline
void rtw8852bx_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
{
rtw8852bx_info.bb_cfg_txrx_path(rtwdev);
}
static inline
void rtw8852bx_bb_cfg_tx_path(struct rtw89_dev *rtwdev, u8 tx_path)
{
rtw8852bx_info.bb_cfg_tx_path(rtwdev, tx_path);
}
static inline
void rtw8852bx_bb_ctrl_rx_path(struct rtw89_dev *rtwdev,
enum rtw89_rf_path_bit rx_path)
{
rtw8852bx_info.bb_ctrl_rx_path(rtwdev, rx_path);
}
static inline
void rtw8852bx_bb_set_plcp_tx(struct rtw89_dev *rtwdev)
{
rtw8852bx_info.bb_set_plcp_tx(rtwdev);
}
static inline
void rtw8852bx_bb_set_power(struct rtw89_dev *rtwdev, s16 pwr_dbm,
enum rtw89_phy_idx idx)
{
rtw8852bx_info.bb_set_power(rtwdev, pwr_dbm, idx);
}
static inline
void rtw8852bx_bb_set_pmac_pkt_tx(struct rtw89_dev *rtwdev, u8 enable,
u16 tx_cnt, u16 period, u16 tx_time,
enum rtw89_phy_idx idx)
{
rtw8852bx_info.bb_set_pmac_pkt_tx(rtwdev, enable, tx_cnt, period, tx_time, idx);
}
static inline
void rtw8852bx_bb_backup_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx idx,
struct rtw8852bx_bb_tssi_bak *bak)
{
rtw8852bx_info.bb_backup_tssi(rtwdev, idx, bak);
}
static inline
void rtw8852bx_bb_restore_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx idx,
const struct rtw8852bx_bb_tssi_bak *bak)
{
rtw8852bx_info.bb_restore_tssi(rtwdev, idx, bak);
}
static inline
void rtw8852bx_bb_tx_mode_switch(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx idx, u8 mode)
{
rtw8852bx_info.bb_tx_mode_switch(rtwdev, idx, mode);
}
static inline
void rtw8852bx_set_channel_mac(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan, u8 mac_idx)
{
rtw8852bx_info.set_channel_mac(rtwdev, chan, mac_idx);
}
static inline
void rtw8852bx_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
{
rtw8852bx_info.set_channel_bb(rtwdev, chan, phy_idx);
}
static inline
void rtw8852bx_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
rtw8852bx_info.ctrl_nbtg_bt_tx(rtwdev, en, phy_idx);
}
static inline
void rtw8852bx_ctrl_btg_bt_rx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
rtw8852bx_info.ctrl_btg_bt_rx(rtwdev, en, phy_idx);
}
static inline
void rtw8852bx_query_ppdu(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu,
struct ieee80211_rx_status *status)
{
rtw8852bx_info.query_ppdu(rtwdev, phy_ppdu, status);
}
static inline
int rtw8852bx_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
enum rtw89_efuse_block block)
{
return rtw8852bx_info.read_efuse(rtwdev, log_map, block);
}
static inline
int rtw8852bx_read_phycap(struct rtw89_dev *rtwdev, u8 *phycap_map)
{
return rtw8852bx_info.read_phycap(rtwdev, phycap_map);
}
static inline
void rtw8852bx_power_trim(struct rtw89_dev *rtwdev)
{
rtw8852bx_info.power_trim(rtwdev);
}
static inline
void rtw8852bx_set_txpwr(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
{
rtw8852bx_info.set_txpwr(rtwdev, chan, phy_idx);
}
static inline
void rtw8852bx_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
rtw8852bx_info.set_txpwr_ctrl(rtwdev, phy_idx);
}
static inline
int rtw8852bx_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
return rtw8852bx_info.init_txpwr_unit(rtwdev, phy_idx);
}
static inline
void rtw8852bx_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
s8 pw_ofst, enum rtw89_mac_idx mac_idx)
{
rtw8852bx_info.set_txpwr_ul_tb_offset(rtwdev, pw_ofst, mac_idx);
}
static inline
u8 rtw8852bx_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path)
{
return rtw8852bx_info.get_thermal(rtwdev, rf_path);
}
static inline
void rtw8852bx_adc_cfg(struct rtw89_dev *rtwdev, u8 bw, u8 path)
{
rtw8852bx_info.adc_cfg(rtwdev, bw, path);
}
static inline
void rtw8852bx_btc_init_cfg(struct rtw89_dev *rtwdev)
{
rtw8852bx_info.btc_init_cfg(rtwdev);
}
static inline
void rtw8852bx_btc_set_wl_pri(struct rtw89_dev *rtwdev, u8 map, bool state)
{
rtw8852bx_info.btc_set_wl_pri(rtwdev, map, state);
}
static inline
s8 rtw8852bx_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val)
{
return rtw8852bx_info.btc_get_bt_rssi(rtwdev, val);
}
static inline
void rtw8852bx_btc_update_bt_cnt(struct rtw89_dev *rtwdev)
{
rtw8852bx_info.btc_update_bt_cnt(rtwdev);
}
static inline
void rtw8852bx_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
{
rtw8852bx_info.btc_wl_s1_standby(rtwdev, state);
}
static inline
void rtw8852bx_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
{
rtw8852bx_info.btc_set_wl_rx_gain(rtwdev, level);
}
#endif

View File

@ -8,6 +8,7 @@
#include "phy.h"
#include "reg.h"
#include "rtw8852b.h"
#include "rtw8852b_common.h"
#include "rtw8852b_rfk.h"
#include "rtw8852b_rfk_table.h"
#include "rtw8852b_table.h"
@ -20,7 +21,7 @@
#define RTW8852B_RF_REL_VERSION 34
#define RTW8852B_DPK_VER 0x0d
#define RTW8852B_DPK_RF_PATH 2
#define RTW8852B_DPK_KIP_REG_NUM 2
#define RTW8852B_DPK_KIP_REG_NUM 3
#define _TSSI_DE_MASK GENMASK(21, 12)
#define ADDC_T_AVG 100
@ -846,7 +847,7 @@ static bool _iqk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
case ID_NBTXK:
rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_EN, 0x0);
rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x011);
iqk_cmd = 0x308 | (1 << (4 + path));
iqk_cmd = 0x408 | (1 << (4 + path));
break;
case ID_NBRXK:
rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_EN, 0x1);
@ -1078,7 +1079,7 @@ static bool _iqk_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u8
{
struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
bool kfail;
u8 gp = 0x3;
u8 gp = 0x2;
switch (iqk_info->iqk_band[path]) {
case RTW89_BAND_2G:
@ -3433,13 +3434,13 @@ static void _tssi_hw_tx(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
rx_path = RF_ABCD; /* don't change path, but still set others */
if (enable) {
rtw8852b_bb_set_plcp_tx(rtwdev);
rtw8852b_bb_cfg_tx_path(rtwdev, path);
rtw8852b_bb_ctrl_rx_path(rtwdev, rx_path);
rtw8852b_bb_set_power(rtwdev, pwr_dbm, phy);
rtw8852bx_bb_set_plcp_tx(rtwdev);
rtw8852bx_bb_cfg_tx_path(rtwdev, path);
rtw8852bx_bb_ctrl_rx_path(rtwdev, rx_path);
rtw8852bx_bb_set_power(rtwdev, pwr_dbm, phy);
}
rtw8852b_bb_set_pmac_pkt_tx(rtwdev, enable, cnt, period, 20, phy);
rtw8852bx_bb_set_pmac_pkt_tx(rtwdev, enable, cnt, period, 20, phy);
}
static void _tssi_backup_bb_registers(struct rtw89_dev *rtwdev,
@ -3578,7 +3579,7 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
u32 tssi_cw_rpt[RTW8852B_TSSI_PATH_NR] = {0};
u8 channel = chan->channel;
u8 ch_idx = _tssi_ch_to_idx(rtwdev, channel);
struct rtw8852b_bb_tssi_bak tssi_bak;
struct rtw8852bx_bb_tssi_bak tssi_bak;
s32 aliment_diff, tssi_cw_default;
u32 start_time, finish_time;
u32 bb_reg_backup[8] = {0};
@ -3626,7 +3627,7 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
else
band = TSSI_ALIMK_2G;
rtw8852b_bb_backup_tssi(rtwdev, phy, &tssi_bak);
rtw8852bx_bb_backup_tssi(rtwdev, phy, &tssi_bak);
_tssi_backup_bb_registers(rtwdev, phy, bb_reg, bb_reg_backup, ARRAY_SIZE(bb_reg_backup));
rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_AVG, 0x8);
@ -3730,8 +3731,8 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
out:
_tssi_reload_bb_registers(rtwdev, phy, bb_reg, bb_reg_backup, ARRAY_SIZE(bb_reg_backup));
rtw8852b_bb_restore_tssi(rtwdev, phy, &tssi_bak);
rtw8852b_bb_tx_mode_switch(rtwdev, phy, 0);
rtw8852bx_bb_restore_tssi(rtwdev, phy, &tssi_bak);
rtw8852bx_bb_tx_mode_switch(rtwdev, phy, 0);
finish_time = ktime_get_ns();
tssi_info->tssi_alimk_time += finish_time - start_time;

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,7 @@ extern const struct rtw89_phy_table rtw89_8852b_phy_bb_gain_table;
extern const struct rtw89_phy_table rtw89_8852b_phy_radioa_table;
extern const struct rtw89_phy_table rtw89_8852b_phy_radiob_table;
extern const struct rtw89_phy_table rtw89_8852b_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8852b_byr_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852b_trk_cfg;
extern const u8 rtw89_8852b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
extern const struct rtw89_rfe_parms rtw89_8852b_dflt_parms;
#endif

View File

@ -10,6 +10,7 @@
#include "rtw8852b.h"
static const struct rtw89_pci_info rtw8852b_pci_info = {
.gen_def = &rtw89_pci_gen_ax,
.txbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_mode = MAC_AX_RXBD_PKT,
@ -24,6 +25,8 @@ static const struct rtw89_pci_info rtw8852b_pci_info = {
.autok_en = MAC_AX_PCIE_DISABLE,
.io_rcy_en = MAC_AX_PCIE_DISABLE,
.io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
.rx_ring_eq_is_full = false,
.check_rx_tag = false,
.init_cfg_reg = R_AX_PCIE_INIT_CFG1,
.txhci_en_bit = B_AX_TXHCI_EN,
@ -33,6 +36,7 @@ static const struct rtw89_pci_info rtw8852b_pci_info = {
.max_tag_num_mask = B_AX_MAX_TAG_NUM,
.rxbd_rwptr_clr_reg = R_AX_RXBD_RWPTR_CLR,
.txbd_rwptr_clr2_reg = 0,
.dma_io_stop = {R_AX_PCIE_DMA_STOP1, B_AX_STOP_PCIEIO},
.dma_stop1 = {R_AX_PCIE_DMA_STOP1, B_AX_TX_STOP1_MASK_V1},
.dma_stop2 = {0},
.dma_busy1 = {R_AX_PCIE_DMA_BUSY1, DMA_BUSY1_CHECK_V1},
@ -41,6 +45,8 @@ static const struct rtw89_pci_info rtw8852b_pci_info = {
.rpwm_addr = R_AX_PCIE_HRPWM,
.cpwm_addr = R_AX_CPWM,
.mit_addr = R_AX_INT_MIT_RX,
.wp_sel_addr = 0,
.tx_dma_ch_mask = BIT(RTW89_TXCH_ACH4) | BIT(RTW89_TXCH_ACH5) |
BIT(RTW89_TXCH_ACH6) | BIT(RTW89_TXCH_ACH7) |
BIT(RTW89_TXCH_CH10) | BIT(RTW89_TXCH_CH11),
@ -58,6 +64,7 @@ static const struct rtw89_pci_info rtw8852b_pci_info = {
static const struct rtw89_driver_info rtw89_8852be_info = {
.chip = &rtw8852b_chip_info,
.quirks = NULL,
.bus = {
.pci = &rtw8852b_pci_info,
},

13
rtw8852bt.h Normal file
View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2024 Realtek Corporation
*/
#ifndef __RTW89_8852BT_H__
#define __RTW89_8852BT_H__
#include "core.h"
#define RF_PATH_NUM_8852BT 2
#define BB_PATH_NUM_8852BT 2
#endif

4019
rtw8852bt_rfk.c Normal file

File diff suppressed because it is too large Load Diff

22
rtw8852bt_rfk.h Normal file
View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2024 Realtek Corporation
*/
#ifndef __RTW89_8852BT_RFK_H__
#define __RTW89_8852BT_RFK_H__
#include "core.h"
void rtw8852bt_rck(struct rtw89_dev *rtwdev);
void rtw8852bt_dack(struct rtw89_dev *rtwdev);
void rtw8852bt_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void rtw8852bt_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void rtw8852bt_dpk_init(struct rtw89_dev *rtwdev);
void rtw8852bt_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
void rtw8852bt_dpk_track(struct rtw89_dev *rtwdev);
void rtw8852bt_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_en);
void rtw8852bt_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
void rtw8852bt_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
enum rtw89_phy_idx phy_idx);
#endif

490
rtw8852bt_rfk_table.c Normal file
View File

@ -0,0 +1,490 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2024 Realtek Corporation
*/
#include "rtw8852bt_rfk_table.h"
static const struct rtw89_reg5_def rtw8852bt_tssi_sys_defs[] = {
RTW89_DECL_RFK_WM(0x12a8, 0x0000000f, 0x4),
RTW89_DECL_RFK_WM(0x32a8, 0x0000000f, 0x4),
RTW89_DECL_RFK_WM(0x12bc, 0x000ffff0, 0x5555),
RTW89_DECL_RFK_WM(0x32bc, 0x000ffff0, 0x5555),
RTW89_DECL_RFK_WM(0x0300, 0xff000000, 0x16),
RTW89_DECL_RFK_WM(0x0304, 0x000000ff, 0x19),
RTW89_DECL_RFK_WM(0x0314, 0xffff0000, 0x2041),
RTW89_DECL_RFK_WM(0x0318, 0xffffffff, 0x2041),
RTW89_DECL_RFK_WM(0x0318, 0xffffffff, 0x20012041),
RTW89_DECL_RFK_WM(0x0020, 0x00006000, 0x3),
RTW89_DECL_RFK_WM(0x0024, 0x00006000, 0x3),
RTW89_DECL_RFK_WM(0x0704, 0xffff0000, 0x601e),
RTW89_DECL_RFK_WM(0x2704, 0xffff0000, 0x601e),
RTW89_DECL_RFK_WM(0x0700, 0xf0000000, 0x4),
RTW89_DECL_RFK_WM(0x2700, 0xf0000000, 0x4),
RTW89_DECL_RFK_WM(0x0650, 0x3c000000, 0x0),
RTW89_DECL_RFK_WM(0x2650, 0x3c000000, 0x0),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_sys_defs);
static const struct rtw89_reg5_def rtw8852bt_tssi_sys_a_defs_2g[] = {
RTW89_DECL_RFK_WM(0x120c, 0x000000ff, 0x33),
RTW89_DECL_RFK_WM(0x12c0, 0x0ff00000, 0x33),
RTW89_DECL_RFK_WM(0x58f8, 0x40000000, 0x1),
RTW89_DECL_RFK_WM(0x0304, 0x0000ff00, 0x1e),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_sys_a_defs_2g);
static const struct rtw89_reg5_def rtw8852bt_tssi_sys_a_defs_5g[] = {
RTW89_DECL_RFK_WM(0x120c, 0x000000ff, 0x44),
RTW89_DECL_RFK_WM(0x12c0, 0x0ff00000, 0x44),
RTW89_DECL_RFK_WM(0x58f8, 0x40000000, 0x0),
RTW89_DECL_RFK_WM(0x0304, 0x0000ff00, 0x1d),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_sys_a_defs_5g);
static const struct rtw89_reg5_def rtw8852bt_tssi_sys_b_defs_2g[] = {
RTW89_DECL_RFK_WM(0x32c0, 0x0ff00000, 0x33),
RTW89_DECL_RFK_WM(0x320c, 0x000000ff, 0x33),
RTW89_DECL_RFK_WM(0x78f8, 0x40000000, 0x1),
RTW89_DECL_RFK_WM(0x0304, 0x0000ff00, 0x1e),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_sys_b_defs_2g);
static const struct rtw89_reg5_def rtw8852bt_tssi_sys_b_defs_5g[] = {
RTW89_DECL_RFK_WM(0x32c0, 0x0ff00000, 0x44),
RTW89_DECL_RFK_WM(0x320c, 0x000000ff, 0x44),
RTW89_DECL_RFK_WM(0x78f8, 0x40000000, 0x0),
RTW89_DECL_RFK_WM(0x0304, 0x0000ff00, 0x1d),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_sys_b_defs_5g);
static const struct rtw89_reg5_def rtw8852bt_tssi_init_txpwr_defs_a[] = {
RTW89_DECL_RFK_WM(0x566c, 0x00001000, 0x0),
RTW89_DECL_RFK_WM(0x5800, 0xffffffff, 0x003f807f),
RTW89_DECL_RFK_WM(0x580c, 0x0000007f, 0x40),
RTW89_DECL_RFK_WM(0x580c, 0x0fffff00, 0x00040),
RTW89_DECL_RFK_WM(0x5810, 0xffffffff, 0x59010000),
RTW89_DECL_RFK_WM(0x5814, 0x01ffffff, 0x002d000),
RTW89_DECL_RFK_WM(0x5814, 0xf8000000, 0x00),
RTW89_DECL_RFK_WM(0x5818, 0xffffffff, 0x002c1800),
RTW89_DECL_RFK_WM(0x581c, 0x3fffffff, 0x1dc80280),
RTW89_DECL_RFK_WM(0x5820, 0xffffffff, 0x00002080),
RTW89_DECL_RFK_WM(0x580c, 0x10000000, 0x1),
RTW89_DECL_RFK_WM(0x580c, 0x40000000, 0x1),
RTW89_DECL_RFK_WM(0x5834, 0x3fffffff, 0x000115f2),
RTW89_DECL_RFK_WM(0x5838, 0x7fffffff, 0x0000121),
RTW89_DECL_RFK_WM(0x5854, 0x3fffffff, 0x000115f2),
RTW89_DECL_RFK_WM(0x5858, 0x7fffffff, 0x0000121),
RTW89_DECL_RFK_WM(0x5860, 0x80000000, 0x0),
RTW89_DECL_RFK_WM(0x5864, 0x07ffffff, 0x00801ff),
RTW89_DECL_RFK_WM(0x5898, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x589c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x58a4, 0x000000ff, 0x16),
RTW89_DECL_RFK_WM(0x58b0, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x58b4, 0x7fffffff, 0x0a002000),
RTW89_DECL_RFK_WM(0x58b8, 0x7fffffff, 0x00007628),
RTW89_DECL_RFK_WM(0x58bc, 0x07ffffff, 0x7a7807f),
RTW89_DECL_RFK_WM(0x58c0, 0xfffe0000, 0x003f),
RTW89_DECL_RFK_WM(0x58c4, 0xffffffff, 0x0003ffff),
RTW89_DECL_RFK_WM(0x58c8, 0x00ffffff, 0x000000),
RTW89_DECL_RFK_WM(0x58c8, 0xf0000000, 0x0),
RTW89_DECL_RFK_WM(0x58cc, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x58d0, 0x07ffffff, 0x2008101),
RTW89_DECL_RFK_WM(0x58d4, 0x000000ff, 0x00),
RTW89_DECL_RFK_WM(0x58d4, 0x0003fe00, 0x0ff),
RTW89_DECL_RFK_WM(0x58d4, 0x07fc0000, 0x100),
RTW89_DECL_RFK_WM(0x58d8, 0xffffffff, 0x8008016c),
RTW89_DECL_RFK_WM(0x58dc, 0x0001ffff, 0x0807f),
RTW89_DECL_RFK_WM(0x58dc, 0xfff00000, 0xc00),
RTW89_DECL_RFK_WM(0x58f0, 0x0003ffff, 0x001ff),
RTW89_DECL_RFK_WM(0x58f4, 0x000fffff, 0x000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_init_txpwr_defs_a);
static const struct rtw89_reg5_def rtw8852bt_tssi_init_txpwr_defs_b[] = {
RTW89_DECL_RFK_WM(0x566c, 0x00001000, 0x0),
RTW89_DECL_RFK_WM(0x7800, 0xffffffff, 0x003f807f),
RTW89_DECL_RFK_WM(0x780c, 0x0000007f, 0x40),
RTW89_DECL_RFK_WM(0x780c, 0x0fffff00, 0x00040),
RTW89_DECL_RFK_WM(0x7810, 0xffffffff, 0x59010000),
RTW89_DECL_RFK_WM(0x7814, 0x01ffffff, 0x002d000),
RTW89_DECL_RFK_WM(0x7814, 0xf8000000, 0x00),
RTW89_DECL_RFK_WM(0x7818, 0xffffffff, 0x002c1800),
RTW89_DECL_RFK_WM(0x781c, 0x3fffffff, 0x1dc80280),
RTW89_DECL_RFK_WM(0x7820, 0xffffffff, 0x00002080),
RTW89_DECL_RFK_WM(0x780c, 0x10000000, 0x1),
RTW89_DECL_RFK_WM(0x780c, 0x40000000, 0x1),
RTW89_DECL_RFK_WM(0x7834, 0x3fffffff, 0x000115f2),
RTW89_DECL_RFK_WM(0x7838, 0x7fffffff, 0x0000121),
RTW89_DECL_RFK_WM(0x7854, 0x3fffffff, 0x000115f2),
RTW89_DECL_RFK_WM(0x7858, 0x7fffffff, 0x0000121),
RTW89_DECL_RFK_WM(0x7860, 0x80000000, 0x0),
RTW89_DECL_RFK_WM(0x7864, 0x07ffffff, 0x00801ff),
RTW89_DECL_RFK_WM(0x7898, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x789c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x78a4, 0x000000ff, 0x16),
RTW89_DECL_RFK_WM(0x78b0, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x78b4, 0x7fffffff, 0x0a002000),
RTW89_DECL_RFK_WM(0x78b8, 0x7fffffff, 0x00007628),
RTW89_DECL_RFK_WM(0x78bc, 0x07ffffff, 0x7a7807f),
RTW89_DECL_RFK_WM(0x78c0, 0xfffe0000, 0x003f),
RTW89_DECL_RFK_WM(0x78c4, 0xffffffff, 0x0003ffff),
RTW89_DECL_RFK_WM(0x78c8, 0x00ffffff, 0x000000),
RTW89_DECL_RFK_WM(0x78c8, 0xf0000000, 0x0),
RTW89_DECL_RFK_WM(0x78cc, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x78d0, 0x07ffffff, 0x2008101),
RTW89_DECL_RFK_WM(0x78d4, 0x000000ff, 0x00),
RTW89_DECL_RFK_WM(0x78d4, 0x0003fe00, 0x0ff),
RTW89_DECL_RFK_WM(0x78d4, 0x07fc0000, 0x100),
RTW89_DECL_RFK_WM(0x78d8, 0xffffffff, 0x8008016c),
RTW89_DECL_RFK_WM(0x78dc, 0x0001ffff, 0x0807f),
RTW89_DECL_RFK_WM(0x78dc, 0xfff00000, 0xc00),
RTW89_DECL_RFK_WM(0x78f0, 0x0003ffff, 0x001ff),
RTW89_DECL_RFK_WM(0x78f4, 0x000fffff, 0x000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_init_txpwr_defs_b);
static const struct rtw89_reg5_def rtw8852bt_tssi_init_txpwr_he_tb_defs_a[] = {
RTW89_DECL_RFK_WM(0x58a0, 0xffffffff, 0x000000fe),
RTW89_DECL_RFK_WM(0x58e4, 0x0000007f, 0x1f),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_init_txpwr_he_tb_defs_a);
static const struct rtw89_reg5_def rtw8852bt_tssi_init_txpwr_he_tb_defs_b[] = {
RTW89_DECL_RFK_WM(0x78a0, 0xffffffff, 0x000000fe),
RTW89_DECL_RFK_WM(0x78e4, 0x0000007f, 0x1f),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_init_txpwr_he_tb_defs_b);
static const struct rtw89_reg5_def rtw8852bt_tssi_dck_defs_a[] = {
RTW89_DECL_RFK_WM(0x580c, 0x0fff0000, 0x000),
RTW89_DECL_RFK_WM(0x5814, 0x003ff000, 0x0ef),
RTW89_DECL_RFK_WM(0x5814, 0x18000000, 0x0),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_dck_defs_a);
static const struct rtw89_reg5_def rtw8852bt_tssi_dck_defs_b[] = {
RTW89_DECL_RFK_WM(0x780c, 0x0fff0000, 0x000),
RTW89_DECL_RFK_WM(0x7814, 0x003ff000, 0x0ef),
RTW89_DECL_RFK_WM(0x7814, 0x18000000, 0x0),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_dck_defs_b);
static const struct rtw89_reg5_def rtw8852bt_tssi_dac_gain_defs_a[] = {
RTW89_DECL_RFK_WM(0x58b0, 0x00000400, 0x1),
RTW89_DECL_RFK_WM(0x58b0, 0x00000fff, 0x000),
RTW89_DECL_RFK_WM(0x58b0, 0x00000800, 0x1),
RTW89_DECL_RFK_WM(0x5a00, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a04, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a08, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a0c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a10, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a14, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a18, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a1c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a20, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a24, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a28, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a2c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a30, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a34, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a38, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a3c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a40, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a44, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a48, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a4c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a50, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a54, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a58, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a5c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a60, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a64, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a68, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a6c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a70, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a74, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a78, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a7c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a80, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a84, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a88, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a8c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a90, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a94, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a98, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5a9c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5aa0, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5aa4, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5aa8, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5aac, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5ab0, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5ab4, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5ab8, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5abc, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5ac0, 0xffffffff, 0x00000000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_dac_gain_defs_a);
static const struct rtw89_reg5_def rtw8852bt_tssi_dac_gain_defs_b[] = {
RTW89_DECL_RFK_WM(0x78b0, 0x00000fff, 0x000),
RTW89_DECL_RFK_WM(0x78b0, 0x00000800, 0x1),
RTW89_DECL_RFK_WM(0x7a00, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a04, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a08, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a0c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a10, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a14, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a18, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a1c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a20, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a24, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a28, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a2c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a30, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a34, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a38, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a3c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a40, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a44, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a48, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a4c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a50, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a54, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a58, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a5c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a60, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a64, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a68, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a6c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a70, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a74, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a78, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a7c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a80, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a84, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a88, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a8c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a90, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a94, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a98, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7a9c, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7aa0, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7aa4, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7aa8, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7aac, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7ab0, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7ab4, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7ab8, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7abc, 0xffffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7ac0, 0xffffffff, 0x00000000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_dac_gain_defs_b);
static const struct rtw89_reg5_def rtw8852bt_tssi_slope_a_defs_2g[] = {
RTW89_DECL_RFK_WM(0x5608, 0x07ffffff, 0x0801008),
RTW89_DECL_RFK_WM(0x560c, 0x07ffffff, 0x0201020),
RTW89_DECL_RFK_WM(0x5610, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x5614, 0x07ffffff, 0x0804008),
RTW89_DECL_RFK_WM(0x5618, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x561c, 0x000001ff, 0x008),
RTW89_DECL_RFK_WM(0x561c, 0xffff0000, 0x0808),
RTW89_DECL_RFK_WM(0x5620, 0xffffffff, 0x08081e28),
RTW89_DECL_RFK_WM(0x5624, 0xffffffff, 0x08080808),
RTW89_DECL_RFK_WM(0x5628, 0xffffffff, 0x08081e28),
RTW89_DECL_RFK_WM(0x562c, 0x0000ffff, 0x0808),
RTW89_DECL_RFK_WM(0x581c, 0x00100000, 0x1),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_slope_a_defs_2g);
static const struct rtw89_reg5_def rtw8852bt_tssi_slope_a_defs_5g[] = {
RTW89_DECL_RFK_WM(0x5608, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x560c, 0x07ffffff, 0x0201019),
RTW89_DECL_RFK_WM(0x5610, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x5614, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x5618, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x561c, 0x000001ff, 0x008),
RTW89_DECL_RFK_WM(0x561c, 0xffff0000, 0x0808),
RTW89_DECL_RFK_WM(0x5620, 0xffffffff, 0x08081808),
RTW89_DECL_RFK_WM(0x5624, 0xffffffff, 0x08080808),
RTW89_DECL_RFK_WM(0x5628, 0xffffffff, 0x08080808),
RTW89_DECL_RFK_WM(0x562c, 0x0000ffff, 0x0808),
RTW89_DECL_RFK_WM(0x581c, 0x00100000, 0x1),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_slope_a_defs_5g);
static const struct rtw89_reg5_def rtw8852bt_tssi_slope_b_defs_2g[] = {
RTW89_DECL_RFK_WM(0x7608, 0x07ffffff, 0x0801008),
RTW89_DECL_RFK_WM(0x760c, 0x07ffffff, 0x0201020),
RTW89_DECL_RFK_WM(0x7610, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x7614, 0x07ffffff, 0x0804008),
RTW89_DECL_RFK_WM(0x7618, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x761c, 0x000001ff, 0x008),
RTW89_DECL_RFK_WM(0x761c, 0xffff0000, 0x0808),
RTW89_DECL_RFK_WM(0x7620, 0xffffffff, 0x08081e28),
RTW89_DECL_RFK_WM(0x7624, 0xffffffff, 0x08080808),
RTW89_DECL_RFK_WM(0x7628, 0xffffffff, 0x08081e28),
RTW89_DECL_RFK_WM(0x762c, 0x0000ffff, 0x0808),
RTW89_DECL_RFK_WM(0x781c, 0x00100000, 0x1),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_slope_b_defs_2g);
static const struct rtw89_reg5_def rtw8852bt_tssi_slope_b_defs_5g[] = {
RTW89_DECL_RFK_WM(0x7608, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x760c, 0x07ffffff, 0x0201019),
RTW89_DECL_RFK_WM(0x7610, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x7614, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x7618, 0x07ffffff, 0x0201008),
RTW89_DECL_RFK_WM(0x761c, 0x000001ff, 0x008),
RTW89_DECL_RFK_WM(0x761c, 0xffff0000, 0x0808),
RTW89_DECL_RFK_WM(0x7620, 0xffffffff, 0x08081808),
RTW89_DECL_RFK_WM(0x7624, 0xffffffff, 0x08080808),
RTW89_DECL_RFK_WM(0x7628, 0xffffffff, 0x08080808),
RTW89_DECL_RFK_WM(0x762c, 0x0000ffff, 0x0808),
RTW89_DECL_RFK_WM(0x781c, 0x00100000, 0x1),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_slope_b_defs_5g);
static const struct rtw89_reg5_def rtw8852bt_tssi_align_a_2g_all_defs[] = {
RTW89_DECL_RFK_WM(0x5604, 0x80000000, 0x1),
RTW89_DECL_RFK_WM(0x5600, 0x3fffffff, 0x3f2d2721),
RTW89_DECL_RFK_WM(0x5604, 0x003fffff, 0x010101),
RTW89_DECL_RFK_WM(0x5630, 0x3fffffff, 0x029f57c0),
RTW89_DECL_RFK_WM(0x5634, 0x3fffffff, 0x00000077),
RTW89_DECL_RFK_WM(0x5638, 0x000fffff, 0x00000),
RTW89_DECL_RFK_WM(0x563c, 0x3fffffff, 0x029f5bc0),
RTW89_DECL_RFK_WM(0x5640, 0x3fffffff, 0x00000076),
RTW89_DECL_RFK_WM(0x5644, 0x000fffff, 0x00000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_align_a_2g_all_defs);
static const struct rtw89_reg5_def rtw8852bt_tssi_align_a_5g1_all_defs[] = {
RTW89_DECL_RFK_WM(0x5604, 0x80000000, 0x1),
RTW89_DECL_RFK_WM(0x5600, 0x3fffffff, 0x3f2d2721),
RTW89_DECL_RFK_WM(0x5604, 0x003fffff, 0x010101),
RTW89_DECL_RFK_WM(0x5630, 0x3fffffff, 0x007ff3d7),
RTW89_DECL_RFK_WM(0x5634, 0x3fffffff, 0x00000068),
RTW89_DECL_RFK_WM(0x5638, 0x000fffff, 0x00000),
RTW89_DECL_RFK_WM(0x563c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5640, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5644, 0x000fffff, 0x00000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_align_a_5g1_all_defs);
static const struct rtw89_reg5_def rtw8852bt_tssi_align_a_5g2_all_defs[] = {
RTW89_DECL_RFK_WM(0x5604, 0x80000000, 0x1),
RTW89_DECL_RFK_WM(0x5600, 0x3fffffff, 0x3f2d2721),
RTW89_DECL_RFK_WM(0x5604, 0x003fffff, 0x010101),
RTW89_DECL_RFK_WM(0x5630, 0x3fffffff, 0x00a003db),
RTW89_DECL_RFK_WM(0x5634, 0x3fffffff, 0x00000065),
RTW89_DECL_RFK_WM(0x5638, 0x000fffff, 0x00000),
RTW89_DECL_RFK_WM(0x563c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5640, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5644, 0x000fffff, 0x00000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_align_a_5g2_all_defs);
static const struct rtw89_reg5_def rtw8852bt_tssi_align_a_5g3_all_defs[] = {
RTW89_DECL_RFK_WM(0x5604, 0x80000000, 0x1),
RTW89_DECL_RFK_WM(0x5600, 0x3fffffff, 0x3f2d2721),
RTW89_DECL_RFK_WM(0x5604, 0x003fffff, 0x010101),
RTW89_DECL_RFK_WM(0x5630, 0x3fffffff, 0x01101be2),
RTW89_DECL_RFK_WM(0x5634, 0x3fffffff, 0x00000065),
RTW89_DECL_RFK_WM(0x5638, 0x000fffff, 0x00000),
RTW89_DECL_RFK_WM(0x563c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5640, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5644, 0x000fffff, 0x00000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_align_a_5g3_all_defs);
static const struct rtw89_reg5_def rtw8852bt_tssi_align_b_2g_all_defs[] = {
RTW89_DECL_RFK_WM(0x7604, 0x80000000, 0x1),
RTW89_DECL_RFK_WM(0x7600, 0x3fffffff, 0x3f2d2721),
RTW89_DECL_RFK_WM(0x7604, 0x003fffff, 0x010101),
RTW89_DECL_RFK_WM(0x7630, 0x3fffffff, 0x023f3fb9),
RTW89_DECL_RFK_WM(0x7634, 0x3fffffff, 0x00000075),
RTW89_DECL_RFK_WM(0x7638, 0x000fffff, 0x00000),
RTW89_DECL_RFK_WM(0x763c, 0x3fffffff, 0x01df3fb8),
RTW89_DECL_RFK_WM(0x7640, 0x3fffffff, 0x00000074),
RTW89_DECL_RFK_WM(0x7644, 0x000fffff, 0x00000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_align_b_2g_all_defs);
static const struct rtw89_reg5_def rtw8852bt_tssi_align_b_5g1_all_defs[] = {
RTW89_DECL_RFK_WM(0x7604, 0x80000000, 0x1),
RTW89_DECL_RFK_WM(0x7600, 0x3fffffff, 0x3f2d2721),
RTW89_DECL_RFK_WM(0x7604, 0x003fffff, 0x010101),
RTW89_DECL_RFK_WM(0x7630, 0x3fffffff, 0x010017e0),
RTW89_DECL_RFK_WM(0x7634, 0x3fffffff, 0x00000069),
RTW89_DECL_RFK_WM(0x7638, 0x000fffff, 0x00000),
RTW89_DECL_RFK_WM(0x763c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7640, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7644, 0x000fffff, 0x00000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_align_b_5g1_all_defs);
static const struct rtw89_reg5_def rtw8852bt_tssi_align_b_5g2_all_defs[] = {
RTW89_DECL_RFK_WM(0x7604, 0x80000000, 0x1),
RTW89_DECL_RFK_WM(0x7600, 0x3fffffff, 0x3f2d2721),
RTW89_DECL_RFK_WM(0x7604, 0x003fffff, 0x010101),
RTW89_DECL_RFK_WM(0x7630, 0x3fffffff, 0x01201fe2),
RTW89_DECL_RFK_WM(0x7634, 0x3fffffff, 0x00000066),
RTW89_DECL_RFK_WM(0x7638, 0x000fffff, 0x00000),
RTW89_DECL_RFK_WM(0x763c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7640, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7644, 0x000fffff, 0x00000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_align_b_5g2_all_defs);
static const struct rtw89_reg5_def rtw8852bt_tssi_align_b_5g3_all_defs[] = {
RTW89_DECL_RFK_WM(0x7604, 0x80000000, 0x1),
RTW89_DECL_RFK_WM(0x7600, 0x3fffffff, 0x3f2d2721),
RTW89_DECL_RFK_WM(0x7604, 0x003fffff, 0x010101),
RTW89_DECL_RFK_WM(0x7630, 0x3fffffff, 0x01602fe5),
RTW89_DECL_RFK_WM(0x7634, 0x3fffffff, 0x00000068),
RTW89_DECL_RFK_WM(0x7638, 0x000fffff, 0x00000),
RTW89_DECL_RFK_WM(0x763c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7640, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7644, 0x000fffff, 0x00000),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_align_b_5g3_all_defs);
static const struct rtw89_reg5_def rtw8852bt_tssi_slope_defs_a[] = {
RTW89_DECL_RFK_WM(0x5814, 0x00000800, 0x1),
RTW89_DECL_RFK_WM(0x581c, 0x20000000, 0x1),
RTW89_DECL_RFK_WM(0x5814, 0x20000000, 0x1),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_slope_defs_a);
static const struct rtw89_reg5_def rtw8852bt_tssi_slope_defs_b[] = {
RTW89_DECL_RFK_WM(0x7814, 0x00000800, 0x1),
RTW89_DECL_RFK_WM(0x781c, 0x20000000, 0x1),
RTW89_DECL_RFK_WM(0x7814, 0x20000000, 0x1),
};
RTW89_DECLARE_RFK_TBL(rtw8852bt_tssi_slope_defs_b);

38
rtw8852bt_rfk_table.h Normal file
View File

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2024 Realtek Corporation
*/
#ifndef __RTW89_8852BT_RFK_TABLE_H__
#define __RTW89_8852BT_RFK_TABLE_H__
#include "phy.h"
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_sys_defs_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_sys_a_defs_2g_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_sys_a_defs_5g_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_sys_b_defs_2g_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_sys_b_defs_5g_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_init_txpwr_defs_a_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_init_txpwr_defs_b_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_init_txpwr_he_tb_defs_a_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_init_txpwr_he_tb_defs_b_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_dck_defs_a_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_dck_defs_b_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_dac_gain_defs_a_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_dac_gain_defs_b_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_slope_a_defs_2g_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_slope_a_defs_5g_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_slope_b_defs_2g_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_slope_b_defs_5g_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_align_a_2g_all_defs_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_align_a_5g1_all_defs_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_align_a_5g2_all_defs_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_align_a_5g3_all_defs_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_align_b_2g_all_defs_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_align_b_5g1_all_defs_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_align_b_5g2_all_defs_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_align_b_5g3_all_defs_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_slope_defs_a_tbl;
extern const struct rtw89_rfk_tbl rtw8852bt_tssi_slope_defs_b_tbl;
#endif

View File

@ -2,6 +2,7 @@
/* Copyright(c) 2019-2022 Realtek Corporation
*/
#include "chan.h"
#include "coex.h"
#include "debug.h"
#include "fw.h"
@ -72,6 +73,10 @@ static const u32 rtw8852c_c2h_regs[RTW89_H2CREG_MAX] = {
R_AX_C2HREG_DATA3_V1
};
static const u32 rtw8852c_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = {
R_AX_C2HREG_DATA3_V1 + 3, R_AX_DBG_WOW,
};
static const struct rtw89_page_regs rtw8852c_page_regs = {
.hci_fc_ctrl = R_AX_HCI_FC_CTRL_V1,
.ch_page_ctrl = R_AX_CH_PAGE_CTRL_V1,
@ -146,6 +151,10 @@ static const struct rtw89_dig_regs rtw8852c_dig_regs = {
.seg0_pd_reg = R_SEG0R_PD,
.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
.pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK,
.bmode_pd_reg = R_BMODE_PDTH_EN_V1,
.bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1,
.bmode_pd_lower_bound_reg = R_BMODE_PDTH_V1,
.bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1,
.p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK},
.p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK},
.p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1},
@ -162,7 +171,23 @@ static const struct rtw89_dig_regs rtw8852c_dig_regs = {
B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
};
static void rtw8852c_ctrl_btg(struct rtw89_dev *rtwdev, bool btg);
static const struct rtw89_edcca_regs rtw8852c_edcca_regs = {
.edcca_level = R_SEG0R_EDCCA_LVL,
.edcca_mask = B_EDCCA_LVL_MSK0,
.edcca_p_mask = B_EDCCA_LVL_MSK1,
.ppdu_level = R_SEG0R_EDCCA_LVL,
.ppdu_mask = B_EDCCA_LVL_MSK3,
.rpt_a = R_EDCCA_RPT_A,
.rpt_b = R_EDCCA_RPT_B,
.rpt_sel = R_EDCCA_RPT_SEL,
.rpt_sel_mask = B_EDCCA_RPT_SEL_MSK,
.tx_collision_t2r_st = R_TX_COLLISION_T2R_ST,
.tx_collision_t2r_st_mask = B_TX_COLLISION_T2R_ST_M,
};
static void rtw8852c_ctrl_btg_bt_rx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx);
static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path,
enum rtw89_mac_idx mac_idx);
@ -182,6 +207,9 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev)
rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APDM_HPDN);
rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS);
rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0,
B_AX_OCP_L1_MASK, 0x7);
ret = read_poll_timeout(rtw89_read32, val32, val32 & B_AX_RDY_SYSPWR,
1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL);
if (ret)
@ -245,7 +273,7 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev)
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_SRAM2RFC);
if (ret)
return ret;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0, XTAL_SI_LDO_LPS);
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0x10, XTAL_SI_LDO_LPS);
if (ret)
return ret;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_4, 0, XTAL_SI_LPS_CAP);
@ -317,6 +345,7 @@ static int rtw8852c_pwr_off_func(struct rtw89_dev *rtwdev)
return ret;
rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON);
rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, B_AX_FEN_BB_GLB_RSTN | B_AX_FEN_BBRSTB);
rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
B_AX_R_SYM_FEN_WLBBGLB_1 | B_AX_R_SYM_FEN_WLBBFUN_1);
@ -339,8 +368,11 @@ static int rtw8852c_pwr_off_func(struct rtw89_dev *rtwdev)
if (ret)
return ret;
rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, 0x0001A0B0);
rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION);
rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_XTAL_OFF_A_DIE);
rtw89_write32_set(rtwdev, R_AX_SYS_SWR_CTRL1, B_AX_SYM_CTRL_SPS_PWMFREQ);
rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0,
B_AX_REG_ZCDC_H_MASK, 0x3);
rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS);
return 0;
@ -419,11 +451,36 @@ static void rtw8852c_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev,
valid |= _decode_efuse_gain(map->rx_gain_5g_high,
&gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_HIGH],
&gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_5G_HIGH]);
valid |= _decode_efuse_gain(map->rx_gain_6g_l0,
&gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_L0],
&gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_L0]);
valid |= _decode_efuse_gain(map->rx_gain_6g_l1,
&gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_L1],
&gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_L1]);
valid |= _decode_efuse_gain(map->rx_gain_6g_m0,
&gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_M0],
&gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_M0]);
valid |= _decode_efuse_gain(map->rx_gain_6g_m1,
&gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_M1],
&gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_M1]);
valid |= _decode_efuse_gain(map->rx_gain_6g_h0,
&gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_H0],
&gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_H0]);
valid |= _decode_efuse_gain(map->rx_gain_6g_h1,
&gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_H1],
&gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_H1]);
valid |= _decode_efuse_gain(map->rx_gain_6g_uh0,
&gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_UH0],
&gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_UH0]);
valid |= _decode_efuse_gain(map->rx_gain_6g_uh1,
&gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_UH1],
&gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_UH1]);
gain->offset_valid = valid;
}
static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map)
static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
enum rtw89_efuse_block block)
{
struct rtw89_efuse *efuse = &rtwdev->efuse;
struct rtw8852c_efuse *map;
@ -606,10 +663,9 @@ static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
u8 mac_idx)
{
u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx);
u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE,
mac_idx);
u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx);
u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_AX_WMAC_RFMOD, mac_idx);
u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx);
u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXRATE_CHK, mac_idx);
u8 txsc20 = 0, txsc40 = 0, txsc80 = 0;
u8 rf_mod_val = 0, chk_rate_mask = 0;
u32 txsc;
@ -797,7 +853,7 @@ static void rtw8852c_set_gain_error(struct rtw89_dev *rtwdev,
enum rtw89_subband subband,
enum rtw89_rf_path path)
{
const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain;
const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
u8 gain_band = rtw89_subband_to_bb_gain_band(subband);
s32 val;
u32 reg;
@ -1647,15 +1703,15 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
}
rtw8852c_spur_elimination(rtwdev, chan, pri_ch_idx, phy_idx);
rtw8852c_ctrl_btg(rtwdev, chan->band_type == RTW89_BAND_2G);
rtw8852c_ctrl_btg_bt_rx(rtwdev, chan->band_type == RTW89_BAND_2G,
RTW89_PHY_0);
rtw8852c_5m_mask(rtwdev, chan, phy_idx);
if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
rtwdev->hal.cv != CHIP_CAV) {
rtw89_phy_write32_idx(rtwdev, R_P80_AT_HIGH_FREQ,
B_P80_AT_HIGH_FREQ, 0x0, phy_idx);
reg = rtw89_mac_reg_by_idx(R_P80_AT_HIGH_FREQ_BB_WRP,
phy_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_P80_AT_HIGH_FREQ_BB_WRP, phy_idx);
if (chan->primary_channel > chan->channel) {
rtw89_phy_write32_mask(rtwdev,
R_P80_AT_HIGH_FREQ_RU_ALLOC,
@ -1774,6 +1830,7 @@ static void rtw8852c_rfk_init(struct rtw89_dev *rtwdev)
rtwdev->is_tssi_mode[RF_PATH_B] = false;
memset(rfk_mcc, 0, sizeof(*rfk_mcc));
rtw8852c_lck_init(rtwdev);
rtw8852c_dpk_init(rtwdev);
rtw8852c_rck(rtwdev);
rtw8852c_dack(rtwdev);
@ -1859,12 +1916,12 @@ void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
for (i = 0; i < 4; i++) {
/* 1TX */
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, mac_idx);
rtw89_write32_mask(rtwdev, reg,
B_AX_PWR_UL_TB_1T_V1_MASK << (8 * i),
val_1t);
/* 2TX */
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, mac_idx);
rtw89_write32_mask(rtwdev, reg,
B_AX_PWR_UL_TB_2T_V1_MASK << (8 * i),
val_2t);
@ -1962,10 +2019,11 @@ static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
{
const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
u8 band = chan->band_type;
u8 regd = rtw89_regd_get(rtwdev, band);
u8 tx_shape_cck = rtw89_8852c_tx_shape[band][RTW89_RS_CCK][regd];
u8 tx_shape_ofdm = rtw89_8852c_tx_shape[band][RTW89_RS_OFDM][regd];
u8 tx_shape_cck = (*rfe_parms->tx_shape.lmt)[band][RTW89_RS_CCK][regd];
u8 tx_shape_ofdm = (*rfe_parms->tx_shape.lmt)[band][RTW89_RS_OFDM][regd];
if (band == RTW89_BAND_2G)
rtw8852c_bb_set_tx_shape_dfir(rtwdev, chan, tx_shape_cck, phy_idx);
@ -1973,6 +2031,11 @@ static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev,
rtw89_phy_tssi_ctrl_set_bandedge_cfg(rtwdev,
(enum rtw89_mac_idx)phy_idx,
tx_shape_ofdm);
rtw89_phy_write32_set(rtwdev, R_P0_DAC_COMP_POST_DPD_EN,
B_P0_DAC_COMP_POST_DPD_EN);
rtw89_phy_write32_set(rtwdev, R_P1_DAC_COMP_POST_DPD_EN,
B_P1_DAC_COMP_POST_DPD_EN);
}
static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev,
@ -2140,7 +2203,8 @@ static void rtw8852c_bb_cfg_rx_path(struct rtw89_dev *rtwdev, u8 rx_path)
1);
rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS,
1);
rtw8852c_ctrl_btg(rtwdev, band == RTW89_BAND_2G);
rtw8852c_ctrl_btg_bt_rx(rtwdev, band == RTW89_BAND_2G,
RTW89_PHY_0);
rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
rst_mask0, 1);
rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
@ -2181,7 +2245,7 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path,
for (addr = R_AX_MACID_ANT_TABLE;
addr <= R_AX_MACID_ANT_TABLE_LAST; addr += 4) {
reg = rtw89_mac_reg_by_idx(addr, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, addr, mac_idx);
rtw89_write32(rtwdev, reg, 0);
}
@ -2211,14 +2275,15 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path,
for (i = 0; i < cr_size; i++) {
rtw89_debug(rtwdev, RTW89_DBG_TSSI, "0x%x = 0x%x\n",
path_com[i].addr, path_com[i].data);
reg = rtw89_mac_reg_by_idx(path_com[i].addr, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, path_com[i].addr, mac_idx);
rtw89_write32(rtwdev, reg, path_com[i].data);
}
}
static void rtw8852c_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en)
static void rtw8852c_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
if (bt_en) {
if (en) {
rtw89_phy_write32_mask(rtwdev, R_PATH0_FRC_FIR_TYPE_V1,
B_PATH0_FRC_FIR_TYPE_MSK_V1, 0x3);
rtw89_phy_write32_mask(rtwdev, R_PATH1_FRC_FIR_TYPE_V1,
@ -2311,34 +2376,62 @@ static u8 rtw8852c_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_p
static void rtw8852c_btc_set_rfe(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_module *module = &btc->mdinfo;
const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
module->rfe_type = rtwdev->efuse.rfe_type;
module->cv = rtwdev->hal.cv;
module->bt_solo = 0;
module->switch_type = BTC_SWITCH_INTERNAL;
if (ver->fcxinit == 7) {
md->md_v7.rfe_type = rtwdev->efuse.rfe_type;
md->md_v7.kt_ver = rtwdev->hal.cv;
md->md_v7.bt_solo = 0;
md->md_v7.switch_type = BTC_SWITCH_INTERNAL;
if (module->rfe_type > 0)
module->ant.num = (module->rfe_type % 2 ? 2 : 3);
else
module->ant.num = 2;
if (md->md_v7.rfe_type > 0)
md->md_v7.ant.num = (md->md_v7.rfe_type % 2 ? 2 : 3);
else
md->md_v7.ant.num = 2;
module->ant.diversity = 0;
module->ant.isolation = 10;
md->md_v7.ant.diversity = 0;
md->md_v7.ant.isolation = 10;
if (module->ant.num == 3) {
module->ant.type = BTC_ANT_DEDICATED;
module->bt_pos = BTC_BT_ALONE;
if (md->md_v7.ant.num == 3) {
md->md_v7.ant.type = BTC_ANT_DEDICATED;
md->md_v7.bt_pos = BTC_BT_ALONE;
} else {
md->md_v7.ant.type = BTC_ANT_SHARED;
md->md_v7.bt_pos = BTC_BT_BTG;
}
rtwdev->btc.btg_pos = md->md_v7.ant.btg_pos;
rtwdev->btc.ant_type = md->md_v7.ant.type;
} else {
module->ant.type = BTC_ANT_SHARED;
module->bt_pos = BTC_BT_BTG;
md->md.rfe_type = rtwdev->efuse.rfe_type;
md->md.cv = rtwdev->hal.cv;
md->md.bt_solo = 0;
md->md.switch_type = BTC_SWITCH_INTERNAL;
if (md->md.rfe_type > 0)
md->md.ant.num = (md->md.rfe_type % 2 ? 2 : 3);
else
md->md.ant.num = 2;
md->md.ant.diversity = 0;
md->md.ant.isolation = 10;
if (md->md.ant.num == 3) {
md->md.ant.type = BTC_ANT_DEDICATED;
md->md.bt_pos = BTC_BT_ALONE;
} else {
md->md.ant.type = BTC_ANT_SHARED;
md->md.bt_pos = BTC_BT_BTG;
}
rtwdev->btc.btg_pos = md->md.ant.btg_pos;
rtwdev->btc.ant_type = md->md.ant.type;
}
}
static void rtw8852c_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
static void rtw8852c_ctrl_btg_bt_rx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
if (btg) {
if (en) {
rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1,
B_PATH0_BT_SHARE_V1, 0x1);
rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1,
@ -2394,7 +2487,6 @@ void rtw8852c_set_trx_mask(struct rtw89_dev *rtwdev, u8 path, u8 group, u32 val)
static void rtw8852c_btc_init_cfg(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_module *module = &btc->mdinfo;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_mac_ax_coex coex_params = {
.pta_mode = RTW89_MAC_AX_COEX_RTK_MODE,
@ -2413,7 +2505,7 @@ static void rtw8852c_btc_init_cfg(struct rtw89_dev *rtwdev)
rtw89_write_rf(rtwdev, RF_PATH_B, RR_WLSEL, RFREG_MASK, 0x0);
/* set WL Tx thru in TRX mask table if GNT_WL = 0 && BT_S1 = ss group */
if (module->ant.type == BTC_ANT_SHARED) {
if (btc->ant_type == BTC_ANT_SHARED) {
rtw8852c_set_trx_mask(rtwdev,
RF_PATH_A, BTC_BT_SS_GROUP, 0x5ff);
rtw8852c_set_trx_mask(rtwdev,
@ -2648,15 +2740,15 @@ static void rtw8852c_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
switch (level) {
case 0: /* original */
default:
rtw8852c_bb_ctrl_btc_preagc(rtwdev, false);
rtw8852c_ctrl_nbtg_bt_tx(rtwdev, false, RTW89_PHY_0);
btc->dm.wl_lna2 = 0;
break;
case 1: /* for FDD free-run */
rtw8852c_bb_ctrl_btc_preagc(rtwdev, true);
rtw8852c_ctrl_nbtg_bt_tx(rtwdev, true, RTW89_PHY_0);
btc->dm.wl_lna2 = 0;
break;
case 2: /* for BTG Co-Rx*/
rtw8852c_bb_ctrl_btc_preagc(rtwdev, false);
rtw8852c_ctrl_nbtg_bt_tx(rtwdev, false, RTW89_PHY_0);
btc->dm.wl_lna2 = 1;
break;
}
@ -2735,12 +2827,17 @@ static int rtw8852c_mac_enable_bb_rf(struct rtw89_dev *rtwdev)
static int rtw8852c_mac_disable_bb_rf(struct rtw89_dev *rtwdev)
{
rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN,
B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN);
return 0;
}
static const struct rtw89_chanctx_listener rtw8852c_chanctx_listener = {
.callbacks[RTW89_CHANCTX_CALLBACK_RFK] = rtw8852c_rfk_chanctx_cb,
};
#ifdef CONFIG_PM
static const struct wiphy_wowlan_support rtw_wowlan_stub_8852c = {
.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
@ -2753,6 +2850,8 @@ static const struct wiphy_wowlan_support rtw_wowlan_stub_8852c = {
static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.enable_bb_rf = rtw8852c_mac_enable_bb_rf,
.disable_bb_rf = rtw8852c_mac_disable_bb_rf,
.bb_preinit = NULL,
.bb_postinit = NULL,
.bb_reset = rtw8852c_bb_reset,
.bb_sethw = rtw8852c_bb_sethw,
.read_rf = rtw89_phy_read_rf_v1,
@ -2763,7 +2862,9 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.read_phycap = rtw8852c_read_phycap,
.fem_setup = NULL,
.rfe_gpio = NULL,
.rfk_hw_init = NULL,
.rfk_init = rtw8852c_rfk_init,
.rfk_init_late = NULL,
.rfk_channel = rtw8852c_rfk_channel,
.rfk_band_changed = rtw8852c_rfk_band_changed,
.rfk_scan = rtw8852c_rfk_scan,
@ -2773,9 +2874,9 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.set_txpwr_ctrl = rtw8852c_set_txpwr_ctrl,
.init_txpwr_unit = rtw8852c_init_txpwr_unit,
.get_thermal = rtw8852c_get_thermal,
.ctrl_btg = rtw8852c_ctrl_btg,
.ctrl_btg_bt_rx = rtw8852c_ctrl_btg_bt_rx,
.query_ppdu = rtw8852c_query_ppdu,
.bb_ctrl_btc_preagc = rtw8852c_bb_ctrl_btc_preagc,
.ctrl_nbtg_bt_tx = rtw8852c_ctrl_nbtg_bt_tx,
.cfg_txrx_path = rtw8852c_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset,
.pwr_on_func = rtw8852c_pwr_on_func,
@ -2788,6 +2889,12 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.stop_sch_tx = rtw89_mac_stop_sch_tx_v1,
.resume_sch_tx = rtw89_mac_resume_sch_tx_v1,
.h2c_dctl_sec_cam = rtw89_fw_h2c_dctl_sec_cam_v1,
.h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl,
.h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl,
.h2c_ampdu_cmac_tbl = NULL,
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
.btc_set_rfe = rtw8852c_btc_set_rfe,
.btc_init_cfg = rtw8852c_btc_init_cfg,
@ -2804,9 +2911,12 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.chip_id = RTL8852C,
.chip_gen = RTW89_CHIP_AX,
.ops = &rtw8852c_chip_ops,
.mac_def = &rtw89_mac_gen_ax,
.phy_def = &rtw89_phy_gen_ax,
.fw_basename = RTW8852C_FW_BASENAME,
.fw_format_max = RTW8852C_FW_FORMAT_MAX,
.try_ce_fw = false,
.bbmcu_nr = 0,
.needed_fw_elms = 0,
.fifo_size = 458752,
.small_fifo_size = false,
@ -2816,8 +2926,8 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.rsvd_ple_ofst = 0x6f800,
.hfc_param_ini = rtw8852c_hfc_param_ini_pcie,
.dle_mem = rtw8852c_dle_mem_pcie,
.wde_qempty_acq_num = 16,
.wde_qempty_mgq_sel = 16,
.wde_qempty_acq_grpnum = 16,
.wde_qempty_mgq_grpsel = 16,
.rf_base_addr = {0xe000, 0xf000},
.pwr_on_seq = NULL,
.pwr_off_seq = NULL,
@ -2827,21 +2937,27 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
&rtw89_8852c_phy_radioa_table,},
.nctl_table = &rtw89_8852c_phy_nctl_table,
.nctl_post_table = NULL,
.byr_table = &rtw89_8852c_byr_table,
.dflt_parms = &rtw89_8852c_dflt_parms,
.rfe_parms_conf = NULL,
.chanctx_listener = &rtw8852c_chanctx_listener,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = NULL,
.dig_regs = &rtw8852c_dig_regs,
.tssi_dbw_table = &rtw89_8852c_tssi_dbw_table,
.support_chanctx_num = 1,
.support_macid_num = RTW89_MAX_MAC_ID_NUM,
.support_chanctx_num = 2,
.support_rnr = false,
.support_bands = BIT(NL80211_BAND_2GHZ) |
BIT(NL80211_BAND_5GHZ) |
BIT(NL80211_BAND_6GHZ),
.support_bw160 = true,
.support_bandwidths = BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_160),
.support_unii4 = true,
.support_ul_tb_ctrl = false,
.ul_tb_waveform_ctrl = false,
.ul_tb_pwr_diff = true,
.hw_sec_hdr = true,
.rf_path_num = 2,
.tx_nss = 2,
@ -2852,12 +2968,14 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.bacam_num = 8,
.bacam_dynamic_num = 8,
.bacam_ver = RTW89_BACAM_V0_EXT,
.ppdu_max_usr = 8,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 2048,
.limit_efuse_size = 1280,
.dav_phy_efuse_size = 96,
.dav_log_efuse_size = 16,
.efuse_blocks = NULL,
.phycap_addr = 0x590,
.phycap_size = 0x60,
.para_ver = 0x1,
@ -2885,6 +3003,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.hci_func_en_addr = R_AX_HCI_FUNC_EN_V1,
.h2c_desc_size = sizeof(struct rtw89_rxdesc_short),
.txwd_body_size = sizeof(struct rtw89_txwd_body_v1),
.txwd_info_size = sizeof(struct rtw89_txwd_info),
.h2c_ctrl_reg = R_AX_H2CREG_CTRL_V1,
.h2c_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_H2C_DEQ_CNT_MASK >> 8},
.h2c_regs = rtw8852c_h2c_regs,
@ -2892,15 +3011,19 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8},
.c2h_regs = rtw8852c_c2h_regs,
.page_regs = &rtw8852c_page_regs,
.wow_reason_reg = rtw8852c_wow_wakeup_regs,
.cfo_src_fd = false,
.cfo_hw_comp = false,
.dcfo_comp = &rtw8852c_dcfo_comp,
.dcfo_comp_sft = 12,
.imr_info = &rtw8852c_imr_info,
.imr_dmac_table = NULL,
.imr_cmac_table = NULL,
.rrsr_cfgs = &rtw8852c_rrsr_cfgs,
.bss_clr_vld = {R_BSS_CLR_MAP, B_BSS_CLR_MAP_VLD0},
.bss_clr_map_reg = R_BSS_CLR_MAP,
.dma_ch_mask = 0,
.edcca_lvl_reg = R_SEG0R_EDCCA_LVL,
.edcca_regs = &rtw8852c_edcca_regs,
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852c,
#endif

View File

@ -73,9 +73,25 @@ struct rtw8852c_efuse {
u8 bw40_1s_tssi_6g_a[TSSI_MCS_6G_CH_GROUP_NUM];
u8 rsvd14[10];
u8 bw40_1s_tssi_6g_b[TSSI_MCS_6G_CH_GROUP_NUM];
u8 rsvd15[110];
u8 rsvd15[94];
u8 rx_gain_6g_l0;
u8 rsvd16;
u8 rx_gain_6g_l1;
u8 rsvd17;
u8 rx_gain_6g_m0;
u8 rsvd18;
u8 rx_gain_6g_m1;
u8 rsvd19;
u8 rx_gain_6g_h0;
u8 rsvd20;
u8 rx_gain_6g_h1;
u8 rsvd21;
u8 rx_gain_6g_uh0;
u8 rsvd22;
u8 rx_gain_6g_uh1;
u8 rsvd23;
u8 channel_plan_6g;
u8 rsvd16[71];
u8 rsvd24[71];
union {
struct rtw8852c_u_efuse u;
struct rtw8852c_e_efuse e;

View File

@ -2,6 +2,7 @@
/* Copyright(c) 2019-2022 Realtek Corporation
*/
#include "chan.h"
#include "coex.h"
#include "debug.h"
#include "phy.h"
@ -2893,18 +2894,37 @@ static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
enum rtw89_rf_path path)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
enum rtw89_bandwidth bw = chan->band_width;
enum rtw89_band band = chan->band_type;
u32 clk = 0x0;
rtw89_rfk_parser(rtwdev, &rtw8852c_tssi_sys_defs_tbl);
if (path == RF_PATH_A)
switch (bw) {
case RTW89_CHANNEL_WIDTH_80:
clk = 0x1;
break;
case RTW89_CHANNEL_WIDTH_80_80:
case RTW89_CHANNEL_WIDTH_160:
clk = 0x2;
break;
default:
break;
}
if (path == RF_PATH_A) {
rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ADC_CLK,
B_P0_TSSI_ADC_CLK, clk);
rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
&rtw8852c_tssi_sys_defs_2g_a_tbl,
&rtw8852c_tssi_sys_defs_5g_a_tbl);
else
} else {
rtw89_phy_write32_mask(rtwdev, R_P1_TSSI_ADC_CLK,
B_P1_TSSI_ADC_CLK, clk);
rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
&rtw8852c_tssi_sys_defs_2g_b_tbl,
&rtw8852c_tssi_sys_defs_5g_b_tbl);
}
}
static void _tssi_ini_txpwr_ctrl_bb(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
@ -4049,21 +4069,39 @@ void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev,
void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
u8 idx = rfk_mcc->table_idx;
int i;
struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V0] = {};
const struct rtw89_chan *chan;
enum rtw89_entity_mode mode;
u8 chan_idx;
u8 idx;
for (i = 0; i < RTW89_IQK_CHS_NR; i++) {
if (rfk_mcc->ch[idx] == 0)
break;
if (++idx >= RTW89_IQK_CHS_NR)
idx = 0;
mode = rtw89_get_entity_mode(rtwdev);
switch (mode) {
case RTW89_ENTITY_MODE_MCC_PREPARE:
chan_idx = RTW89_SUB_ENTITY_1;
break;
default:
chan_idx = RTW89_SUB_ENTITY_0;
break;
}
rfk_mcc->table_idx = idx;
chan = rtw89_chan_get(rtwdev, chan_idx);
for (idx = 0; idx < ARRAY_SIZE(desc); idx++) {
struct rtw89_rfk_chan_desc *p = &desc[idx];
p->ch = rfk_mcc->ch[idx];
p->has_band = true;
p->band = rfk_mcc->band[idx];
}
idx = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan);
rfk_mcc->ch[idx] = chan->channel;
rfk_mcc->band[idx] = chan->band_type;
rfk_mcc->table_idx = idx;
}
void rtw8852c_rck(struct rtw89_dev *rtwdev)
@ -4213,6 +4251,14 @@ void rtw8852c_rx_dck_track(struct rtw89_dev *rtwdev)
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_STOP);
}
void rtw8852c_dpk_init(struct rtw89_dev *rtwdev)
{
struct rtw89_dpk_info *dpk = &rtwdev->dpk;
dpk->is_dpk_enable = true;
dpk->is_dpk_reload_en = false;
}
void rtw8852c_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
u32 tx_en;
@ -4222,8 +4268,6 @@ void rtw8852c_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
_wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
rtwdev->dpk.is_dpk_enable = true;
rtwdev->dpk.is_dpk_reload_en = false;
_dpk(rtwdev, phy_idx, false);
rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
@ -4361,3 +4405,26 @@ void rtw8852c_wifi_scan_notify(struct rtw89_dev *rtwdev,
else
rtw8852c_tssi_default_txagc(rtwdev, phy_idx, false);
}
void rtw8852c_rfk_chanctx_cb(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_state state)
{
struct rtw89_dpk_info *dpk = &rtwdev->dpk;
u8 path;
switch (state) {
case RTW89_CHANCTX_STATE_MCC_START:
dpk->is_dpk_enable = false;
for (path = 0; path < RTW8852C_DPK_RF_PATH; path++)
_dpk_onoff(rtwdev, path, false);
break;
case RTW89_CHANCTX_STATE_MCC_STOP:
dpk->is_dpk_enable = true;
for (path = 0; path < RTW8852C_DPK_RF_PATH; path++)
_dpk_onoff(rtwdev, path, false);
rtw8852c_dpk(rtwdev, RTW89_PHY_0);
break;
default:
break;
}
}

View File

@ -13,6 +13,7 @@ void rtw8852c_dack(struct rtw89_dev *rtwdev);
void rtw8852c_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool is_afe);
void rtw8852c_rx_dck_track(struct rtw89_dev *rtwdev);
void rtw8852c_dpk_init(struct rtw89_dev *rtwdev);
void rtw8852c_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
void rtw8852c_dpk_track(struct rtw89_dev *rtwdev);
void rtw8852c_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
@ -25,5 +26,7 @@ void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx);
void rtw8852c_lck_init(struct rtw89_dev *rtwdev);
void rtw8852c_lck_track(struct rtw89_dev *rtwdev);
void rtw8852c_rfk_chanctx_cb(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_state state);
#endif

View File

@ -165,11 +165,11 @@ static const struct rtw89_reg5_def rtw8852c_tssi_sys_defs[] = {
RTW89_DECL_RFK_WM(0x12bc, 0x000ffff0, 0xb5b5),
RTW89_DECL_RFK_WM(0x32bc, 0x000ffff0, 0xb5b5),
RTW89_DECL_RFK_WM(0x0300, 0xff000000, 0x16),
RTW89_DECL_RFK_WM(0x0304, 0x0000ffff, 0x1f19),
RTW89_DECL_RFK_WM(0x0308, 0xff000000, 0x1c),
RTW89_DECL_RFK_WM(0x0304, 0x0000ffff, 0x1313),
RTW89_DECL_RFK_WM(0x0308, 0xff000000, 0x13),
RTW89_DECL_RFK_WM(0x0314, 0xffff0000, 0x2041),
RTW89_DECL_RFK_WM(0x0318, 0xffffffff, 0x20012041),
RTW89_DECL_RFK_WM(0x0324, 0xffff0000, 0x2001),
RTW89_DECL_RFK_WM(0x0318, 0xffffffff, 0x00410041),
RTW89_DECL_RFK_WM(0x0324, 0xffff0000, 0x0041),
RTW89_DECL_RFK_WM(0x0020, 0x00006000, 0x3),
RTW89_DECL_RFK_WM(0x0024, 0x00006000, 0x3),
RTW89_DECL_RFK_WM(0x0704, 0xffff0000, 0x601e),
@ -222,7 +222,7 @@ static const struct rtw89_reg5_def rtw8852c_tssi_txpwr_ctrl_bb_defs_a[] = {
RTW89_DECL_RFK_WM(0x5810, 0xffffffff, 0x59010000),
RTW89_DECL_RFK_WM(0x5814, 0x01ffffff, 0x026d000),
RTW89_DECL_RFK_WM(0x5814, 0xf8000000, 0x00),
RTW89_DECL_RFK_WM(0x5818, 0xffffffff, 0x002c1800),
RTW89_DECL_RFK_WM(0x5818, 0xffffffff, 0x002c18e8),
RTW89_DECL_RFK_WM(0x581c, 0x3fffffff, 0x3dc80280),
RTW89_DECL_RFK_WM(0x5820, 0xffffffff, 0x00000080),
RTW89_DECL_RFK_WM(0x58e8, 0x0000003f, 0x03),
@ -251,7 +251,7 @@ static const struct rtw89_reg5_def rtw8852c_tssi_txpwr_ctrl_bb_defs_a[] = {
RTW89_DECL_RFK_WM(0x58d4, 0x07fc0000, 0x100),
RTW89_DECL_RFK_WM(0x58d8, 0xffffffff, 0x8008016c),
RTW89_DECL_RFK_WM(0x58dc, 0x0001ffff, 0x0807f),
RTW89_DECL_RFK_WM(0x58dc, 0xfff00000, 0x800),
RTW89_DECL_RFK_WM(0x58dc, 0xfff00000, 0xc00),
RTW89_DECL_RFK_WM(0x58f0, 0x0003ffff, 0x001ff),
RTW89_DECL_RFK_WM(0x58f4, 0x000fffff, 0x000),
RTW89_DECL_RFK_WM(0x58f8, 0x000fffff, 0x000),
@ -260,14 +260,14 @@ static const struct rtw89_reg5_def rtw8852c_tssi_txpwr_ctrl_bb_defs_a[] = {
RTW89_DECLARE_RFK_TBL(rtw8852c_tssi_txpwr_ctrl_bb_defs_a);
static const struct rtw89_reg5_def rtw8852c_tssi_txpwr_ctrl_bb_defs_b[] = {
RTW89_DECL_RFK_WM(0x566c, 0x00001000, 0x0),
RTW89_DECL_RFK_WM(0x766c, 0x00001000, 0x0),
RTW89_DECL_RFK_WM(0x7800, 0xffffffff, 0x003f807f),
RTW89_DECL_RFK_WM(0x780c, 0x0000007f, 0x40),
RTW89_DECL_RFK_WM(0x780c, 0x0fffff00, 0x00040),
RTW89_DECL_RFK_WM(0x7810, 0xffffffff, 0x59010000),
RTW89_DECL_RFK_WM(0x7814, 0x01ffffff, 0x026d000),
RTW89_DECL_RFK_WM(0x7814, 0xf8000000, 0x00),
RTW89_DECL_RFK_WM(0x7818, 0xffffffff, 0x002c1800),
RTW89_DECL_RFK_WM(0x7818, 0xffffffff, 0x002c18e8),
RTW89_DECL_RFK_WM(0x781c, 0x3fffffff, 0x3dc80280),
RTW89_DECL_RFK_WM(0x7820, 0xffffffff, 0x00000080),
RTW89_DECL_RFK_WM(0x78e8, 0x0000003f, 0x03),
@ -296,7 +296,7 @@ static const struct rtw89_reg5_def rtw8852c_tssi_txpwr_ctrl_bb_defs_b[] = {
RTW89_DECL_RFK_WM(0x78d4, 0x07fc0000, 0x100),
RTW89_DECL_RFK_WM(0x78d8, 0xffffffff, 0x8008016c),
RTW89_DECL_RFK_WM(0x78dc, 0x0001ffff, 0x0807f),
RTW89_DECL_RFK_WM(0x78dc, 0xfff00000, 0x800),
RTW89_DECL_RFK_WM(0x78dc, 0xfff00000, 0xc00),
RTW89_DECL_RFK_WM(0x78f0, 0x0003ffff, 0x001ff),
RTW89_DECL_RFK_WM(0x78f4, 0x000fffff, 0x000),
RTW89_DECL_RFK_WM(0x78f8, 0x000fffff, 0x000),
@ -511,9 +511,9 @@ static const struct rtw89_reg5_def rtw8852c_tssi_set_aligk_default_defs_5g_a[] =
RTW89_DECL_RFK_WM(0x563c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5640, 0x000003ff, 0x000),
RTW89_DECL_RFK_WM(0x5640, 0x000ffc00, 0x000),
RTW89_DECL_RFK_WM(0x5640, 0x3ff00000, 0x000),
RTW89_DECL_RFK_WM(0x5644, 0x000003ff, 0x000),
RTW89_DECL_RFK_WM(0x5644, 0x000ffc00, 0x000),
RTW89_DECL_RFK_WM(0x5640, 0x3ff00000, 0x3e9),
RTW89_DECL_RFK_WM(0x5644, 0x000003ff, 0x039),
RTW89_DECL_RFK_WM(0x5644, 0x000ffc00, 0x07d),
};
RTW89_DECLARE_RFK_TBL(rtw8852c_tssi_set_aligk_default_defs_5g_a);
@ -531,9 +531,9 @@ static const struct rtw89_reg5_def rtw8852c_tssi_set_aligk_default_defs_5g_b[] =
RTW89_DECL_RFK_WM(0x763c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7640, 0x000003ff, 0x000),
RTW89_DECL_RFK_WM(0x7640, 0x000ffc00, 0x000),
RTW89_DECL_RFK_WM(0x7640, 0x3ff00000, 0x000),
RTW89_DECL_RFK_WM(0x7644, 0x000003ff, 0x000),
RTW89_DECL_RFK_WM(0x7644, 0x000ffc00, 0x000),
RTW89_DECL_RFK_WM(0x7640, 0x3ff00000, 0x3e9),
RTW89_DECL_RFK_WM(0x7644, 0x000003ff, 0x039),
RTW89_DECL_RFK_WM(0x7644, 0x000ffc00, 0x07d),
};
RTW89_DECLARE_RFK_TBL(rtw8852c_tssi_set_aligk_default_defs_5g_b);
@ -551,9 +551,9 @@ static const struct rtw89_reg5_def rtw8852c_tssi_set_aligk_default_defs_6g_a[] =
RTW89_DECL_RFK_WM(0x563c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x5640, 0x000003ff, 0x000),
RTW89_DECL_RFK_WM(0x5640, 0x000ffc00, 0x000),
RTW89_DECL_RFK_WM(0x5640, 0x3ff00000, 0x000),
RTW89_DECL_RFK_WM(0x5644, 0x000003ff, 0x000),
RTW89_DECL_RFK_WM(0x5644, 0x000ffc00, 0x000),
RTW89_DECL_RFK_WM(0x5640, 0x3ff00000, 0x3e9),
RTW89_DECL_RFK_WM(0x5644, 0x000003ff, 0x039),
RTW89_DECL_RFK_WM(0x5644, 0x000ffc00, 0x080),
};
RTW89_DECLARE_RFK_TBL(rtw8852c_tssi_set_aligk_default_defs_6g_a);
@ -571,9 +571,9 @@ static const struct rtw89_reg5_def rtw8852c_tssi_set_aligk_default_defs_6g_b[] =
RTW89_DECL_RFK_WM(0x763c, 0x3fffffff, 0x00000000),
RTW89_DECL_RFK_WM(0x7640, 0x000003ff, 0x000),
RTW89_DECL_RFK_WM(0x7640, 0x000ffc00, 0x000),
RTW89_DECL_RFK_WM(0x7640, 0x3ff00000, 0x000),
RTW89_DECL_RFK_WM(0x7644, 0x000003ff, 0x000),
RTW89_DECL_RFK_WM(0x7644, 0x000ffc00, 0x000),
RTW89_DECL_RFK_WM(0x7640, 0x3ff00000, 0x3e9),
RTW89_DECL_RFK_WM(0x7644, 0x000003ff, 0x039),
RTW89_DECL_RFK_WM(0x7644, 0x000ffc00, 0x080),
};
RTW89_DECLARE_RFK_TBL(rtw8852c_tssi_set_aligk_default_defs_6g_b);

File diff suppressed because it is too large Load Diff

View File

@ -12,11 +12,8 @@ extern const struct rtw89_phy_table rtw89_8852c_phy_bb_gain_table;
extern const struct rtw89_phy_table rtw89_8852c_phy_radioa_table;
extern const struct rtw89_phy_table rtw89_8852c_phy_radiob_table;
extern const struct rtw89_phy_table rtw89_8852c_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8852c_byr_table;
extern const struct rtw89_phy_tssi_dbw_table rtw89_8852c_tssi_dbw_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852c_trk_cfg;
extern const u8 rtw89_8852c_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
extern const struct rtw89_rfe_parms rtw89_8852c_dflt_parms;
#endif

View File

@ -19,6 +19,7 @@ static const struct rtw89_pci_bd_idx_addr rtw8852c_bd_idx_addr_low_power = {
};
static const struct rtw89_pci_info rtw8852c_pci_info = {
.gen_def = &rtw89_pci_gen_ax,
.txbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_mode = MAC_AX_RXBD_PKT,
@ -33,6 +34,8 @@ static const struct rtw89_pci_info rtw8852c_pci_info = {
.autok_en = MAC_AX_PCIE_DISABLE,
.io_rcy_en = MAC_AX_PCIE_ENABLE,
.io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
.rx_ring_eq_is_full = false,
.check_rx_tag = false,
.init_cfg_reg = R_AX_HAXI_INIT_CFG1,
.txhci_en_bit = B_AX_TXHCI_EN_V1,
@ -42,6 +45,7 @@ static const struct rtw89_pci_info rtw8852c_pci_info = {
.max_tag_num_mask = B_AX_MAX_TAG_NUM_V1_MASK,
.rxbd_rwptr_clr_reg = R_AX_RXBD_RWPTR_CLR_V1,
.txbd_rwptr_clr2_reg = R_AX_TXBD_RWPTR_CLR2_V1,
.dma_io_stop = {R_AX_HAXI_INIT_CFG1, B_AX_STOP_AXI_MST},
.dma_stop1 = {R_AX_HAXI_DMA_STOP1, B_AX_TX_STOP1_MASK},
.dma_stop2 = {R_AX_HAXI_DMA_STOP2, B_AX_TX_STOP2_ALL},
.dma_busy1 = {R_AX_HAXI_DMA_BUSY1, DMA_BUSY1_CHECK},
@ -50,6 +54,8 @@ static const struct rtw89_pci_info rtw8852c_pci_info = {
.rpwm_addr = R_AX_PCIE_HRPWM_V1,
.cpwm_addr = R_AX_PCIE_CRPWM,
.mit_addr = R_AX_INT_MIT_RX_V1,
.wp_sel_addr = R_AX_WP_ADDR_H_SEL0_3,
.tx_dma_ch_mask = 0,
.bd_idx_addr_low_power = &rtw8852c_bd_idx_addr_low_power,
.dma_addr_set = &rtw89_pci_ch_dma_addr_set_v1,
@ -63,8 +69,31 @@ static const struct rtw89_pci_info rtw8852c_pci_info = {
.recognize_intrs = rtw89_pci_recognize_intrs_v1,
};
static const struct dmi_system_id rtw8852c_pci_quirks[] = {
{
.ident = "Dell Inc. Vostro 16 5640",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 16 5640"),
DMI_MATCH(DMI_PRODUCT_SKU, "0CA0"),
},
.driver_data = (void *)RTW89_QUIRK_PCI_BER,
},
{
.ident = "Dell Inc. Inspiron 16 5640",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 16 5640"),
DMI_MATCH(DMI_PRODUCT_SKU, "0C9F"),
},
.driver_data = (void *)RTW89_QUIRK_PCI_BER,
},
{},
};
static const struct rtw89_driver_info rtw89_8852ce_info = {
.chip = &rtw8852c_chip_info,
.quirks = rtw8852c_pci_quirks,
.bus = {
.pci = &rtw8852c_pci_info,
},

2639
rtw8922a.c Normal file

File diff suppressed because it is too large Load Diff

73
rtw8922a.h Normal file
View File

@ -0,0 +1,73 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2023 Realtek Corporation
*/
#ifndef __RTW89_8922A_H__
#define __RTW89_8922A_H__
#include "core.h"
#define RF_PATH_NUM_8922A 2
#define BB_PATH_NUM_8922A 2
struct rtw8922a_tssi_offset {
u8 cck_tssi[TSSI_CCK_CH_GROUP_NUM];
u8 bw40_tssi[TSSI_MCS_2G_CH_GROUP_NUM];
u8 rsvd[7];
u8 bw40_1s_tssi_5g[TSSI_MCS_5G_CH_GROUP_NUM];
u8 bw_diff_5g[10];
} __packed;
struct rtw8922a_rx_gain {
u8 _2g_ofdm;
u8 _2g_cck;
u8 _5g_low;
u8 _5g_mid;
u8 _5g_high;
} __packed;
struct rtw8922a_rx_gain_6g {
u8 _6g_l0;
u8 _6g_l1;
u8 _6g_m0;
u8 _6g_m1;
u8 _6g_h0;
u8 _6g_h1;
u8 _6g_uh0;
u8 _6g_uh1;
} __packed;
struct rtw8922a_efuse {
u8 country_code[2];
u8 rsvd[0xe];
struct rtw8922a_tssi_offset path_a_tssi;
struct rtw8922a_tssi_offset path_b_tssi;
u8 rsvd1[0x54];
u8 channel_plan;
u8 xtal_k;
u8 rsvd2[0x7];
u8 board_info;
u8 rsvd3[0x8];
u8 rfe_type;
u8 rsvd4[0x5];
u8 path_a_therm;
u8 path_b_therm;
u8 rsvd5[0x2];
struct rtw8922a_rx_gain rx_gain_a;
struct rtw8922a_rx_gain rx_gain_b;
u8 rsvd6[0x22];
u8 bw40_1s_tssi_6g_a[TSSI_MCS_6G_CH_GROUP_NUM];
u8 rsvd7[0xa];
u8 bw40_1s_tssi_6g_b[TSSI_MCS_6G_CH_GROUP_NUM];
u8 rsvd8[0xa];
u8 bw40_1s_tssi_6g_c[TSSI_MCS_6G_CH_GROUP_NUM];
u8 rsvd9[0xa];
u8 bw40_1s_tssi_6g_d[TSSI_MCS_6G_CH_GROUP_NUM];
u8 rsvd10[0xa];
struct rtw8922a_rx_gain_6g rx_gain_6g_a;
struct rtw8922a_rx_gain_6g rx_gain_6g_b;
} __packed;
extern const struct rtw89_chip_info rtw8922a_chip_info;
#endif

391
rtw8922a_rfk.c Normal file
View File

@ -0,0 +1,391 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2023 Realtek Corporation
*/
#include "chan.h"
#include "debug.h"
#include "mac.h"
#include "phy.h"
#include "reg.h"
#include "rtw8922a.h"
#include "rtw8922a_rfk.h"
static void rtw8922a_tssi_cont_en(struct rtw89_dev *rtwdev, bool en,
enum rtw89_rf_path path)
{
static const u32 tssi_trk_man[2] = {R_TSSI_PWR_P0, R_TSSI_PWR_P1};
if (en)
rtw89_phy_write32_mask(rtwdev, tssi_trk_man[path], B_TSSI_CONT_EN, 0);
else
rtw89_phy_write32_mask(rtwdev, tssi_trk_man[path], B_TSSI_CONT_EN, 1);
}
void rtw8922a_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, u8 phy_idx)
{
if (rtwdev->mlo_dbcc_mode == MLO_1_PLUS_1_1RF) {
if (phy_idx == RTW89_PHY_0)
rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_A);
else
rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_B);
} else {
rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_A);
rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_B);
}
}
static
void rtw8922a_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
u8 central_ch, enum rtw89_band band,
enum rtw89_bandwidth bw)
{
const u32 rf_addr[2] = {RR_CFGCH, RR_CFGCH_V1};
struct rtw89_hal *hal = &rtwdev->hal;
u32 rf_reg[RF_PATH_NUM_8922A][2];
u8 synpath;
u32 rf18;
u8 kpath;
u8 path;
u8 i;
rf_reg[RF_PATH_A][0] = rtw89_read_rf(rtwdev, RF_PATH_A, rf_addr[0], RFREG_MASK);
rf_reg[RF_PATH_A][1] = rtw89_read_rf(rtwdev, RF_PATH_A, rf_addr[1], RFREG_MASK);
rf_reg[RF_PATH_B][0] = rtw89_read_rf(rtwdev, RF_PATH_B, rf_addr[0], RFREG_MASK);
rf_reg[RF_PATH_B][1] = rtw89_read_rf(rtwdev, RF_PATH_B, rf_addr[1], RFREG_MASK);
kpath = rtw89_phy_get_kpath(rtwdev, phy);
synpath = rtw89_phy_get_syn_sel(rtwdev, phy);
rf18 = rtw89_read_rf(rtwdev, synpath, RR_CFGCH, RFREG_MASK);
if (rf18 == INV_RF_DATA) {
rtw89_warn(rtwdev, "[RFK] Invalid RF18 value\n");
return;
}
for (path = 0; path < RF_PATH_NUM_8922A; path++) {
if (!(kpath & BIT(path)))
continue;
for (i = 0; i < 2; i++) {
if (rf_reg[path][i] == INV_RF_DATA) {
rtw89_warn(rtwdev,
"[RFK] Invalid RF_0x18 for Path-%d\n", path);
return;
}
rf_reg[path][i] &= ~(RR_CFGCH_BAND1 | RR_CFGCH_BW |
RR_CFGCH_BAND0 | RR_CFGCH_CH);
rf_reg[path][i] |= u32_encode_bits(central_ch, RR_CFGCH_CH);
if (band == RTW89_BAND_2G)
rtw89_write_rf(rtwdev, path, RR_SMD, RR_VCO2, 0x0);
else
rtw89_write_rf(rtwdev, path, RR_SMD, RR_VCO2, 0x1);
switch (band) {
case RTW89_BAND_2G:
default:
break;
case RTW89_BAND_5G:
rf_reg[path][i] |=
u32_encode_bits(CFGCH_BAND1_5G, RR_CFGCH_BAND1) |
u32_encode_bits(CFGCH_BAND0_5G, RR_CFGCH_BAND0);
break;
case RTW89_BAND_6G:
rf_reg[path][i] |=
u32_encode_bits(CFGCH_BAND1_6G, RR_CFGCH_BAND1) |
u32_encode_bits(CFGCH_BAND0_6G, RR_CFGCH_BAND0);
break;
}
switch (bw) {
case RTW89_CHANNEL_WIDTH_5:
case RTW89_CHANNEL_WIDTH_10:
case RTW89_CHANNEL_WIDTH_20:
default:
break;
case RTW89_CHANNEL_WIDTH_40:
rf_reg[path][i] |=
u32_encode_bits(CFGCH_BW_V2_40M, RR_CFGCH_BW_V2);
break;
case RTW89_CHANNEL_WIDTH_80:
rf_reg[path][i] |=
u32_encode_bits(CFGCH_BW_V2_80M, RR_CFGCH_BW_V2);
break;
case RTW89_CHANNEL_WIDTH_160:
rf_reg[path][i] |=
u32_encode_bits(CFGCH_BW_V2_160M, RR_CFGCH_BW_V2);
break;
case RTW89_CHANNEL_WIDTH_320:
rf_reg[path][i] |=
u32_encode_bits(CFGCH_BW_V2_320M, RR_CFGCH_BW_V2);
break;
}
rtw89_write_rf(rtwdev, path, rf_addr[i],
RFREG_MASK, rf_reg[path][i]);
fsleep(100);
}
}
if (hal->cv != CHIP_CAV)
return;
if (band == RTW89_BAND_2G) {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x00003);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c990);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0xebe38);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x00000);
} else {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x00003);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c190);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0xebe38);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x00000);
}
}
void rtw8922a_set_channel_rf(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
{
rtw8922a_ctl_band_ch_bw(rtwdev, phy_idx, chan->channel, chan->band_type,
chan->band_width);
}
enum _rf_syn_pow {
RF_SYN_ON_OFF,
RF_SYN_OFF_ON,
RF_SYN_ALLON,
RF_SYN_ALLOFF,
};
static void rtw8922a_set_syn01_cav(struct rtw89_dev *rtwdev, enum _rf_syn_pow syn)
{
if (syn == RF_SYN_ALLON) {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x2);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x3);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x2);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x3);
} else if (syn == RF_SYN_ON_OFF) {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x2);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x0);
} else if (syn == RF_SYN_OFF_ON) {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x0);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x3);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x2);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x3);
} else if (syn == RF_SYN_ALLOFF) {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x0);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN, 0x0);
}
}
static void rtw8922a_set_syn01_cbv(struct rtw89_dev *rtwdev, enum _rf_syn_pow syn)
{
if (syn == RF_SYN_ALLON) {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN_V1, 0xf);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN_V1, 0xf);
} else if (syn == RF_SYN_ON_OFF) {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN_V1, 0xf);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN_V1, 0x0);
} else if (syn == RF_SYN_OFF_ON) {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN_V1, 0x0);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN_V1, 0xf);
} else if (syn == RF_SYN_ALLOFF) {
rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN_V1, 0x0);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_POW, RR_POW_SYN_V1, 0x0);
}
}
static void rtw8922a_set_syn01(struct rtw89_dev *rtwdev, enum _rf_syn_pow syn)
{
struct rtw89_hal *hal = &rtwdev->hal;
rtw89_debug(rtwdev, RTW89_DBG_RFK, "SYN config=%d\n", syn);
if (hal->cv == CHIP_CAV)
rtw8922a_set_syn01_cav(rtwdev, syn);
else
rtw8922a_set_syn01_cbv(rtwdev, syn);
}
static void rtw8922a_chlk_ktbl_sel(struct rtw89_dev *rtwdev, u8 kpath, u8 idx)
{
u32 tmp;
if (idx > 2) {
rtw89_warn(rtwdev, "[DBCC][ERROR]indx is out of limit!! index(%d)", idx);
return;
}
if (kpath & RF_A) {
rtw89_phy_write32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_EN, 0x1);
rtw89_phy_write32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_IQC_V1, idx);
rtw89_phy_write32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_MDPD_V1, idx);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT, RR_TXG_SEL, 0x4 | idx);
tmp = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL, BIT(0));
rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, tmp);
tmp = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL, BIT(1));
rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G5, tmp);
}
if (kpath & RF_B) {
rtw89_phy_write32_mask(rtwdev, R_COEF_SEL_C1, B_COEF_SEL_EN, 0x1);
rtw89_phy_write32_mask(rtwdev, R_COEF_SEL_C1, B_COEF_SEL_IQC_V1, idx);
rtw89_phy_write32_mask(rtwdev, R_COEF_SEL_C1, B_COEF_SEL_MDPD_V1, idx);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT, RR_TXG_SEL, 0x4 | idx);
tmp = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL_C1, BIT(0));
rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT_C1, B_CFIR_LUT_G3, tmp);
tmp = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL_C1, BIT(1));
rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT_C1, B_CFIR_LUT_G5, tmp);
}
}
static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev)
{
struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {};
enum rtw89_sub_entity_idx sub_entity_idx;
const struct rtw89_chan *chan;
enum rtw89_entity_mode mode;
u8 s0_tbl, s1_tbl;
u8 tbl_sel;
mode = rtw89_get_entity_mode(rtwdev);
switch (mode) {
case RTW89_ENTITY_MODE_MCC_PREPARE:
sub_entity_idx = RTW89_SUB_ENTITY_1;
break;
default:
sub_entity_idx = RTW89_SUB_ENTITY_0;
break;
}
chan = rtw89_chan_get(rtwdev, sub_entity_idx);
for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) {
struct rtw89_rfk_chan_desc *p = &desc[tbl_sel];
p->ch = rfk_mcc->ch[tbl_sel];
p->has_band = true;
p->band = rfk_mcc->band[tbl_sel];
p->has_bw = true;
p->bw = rfk_mcc->bw[tbl_sel];
}
tbl_sel = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan);
rfk_mcc->ch[tbl_sel] = chan->channel;
rfk_mcc->band[tbl_sel] = chan->band_type;
rfk_mcc->bw[tbl_sel] = chan->band_width;
rfk_mcc->table_idx = tbl_sel;
s0_tbl = tbl_sel;
s1_tbl = tbl_sel;
rtw8922a_chlk_ktbl_sel(rtwdev, RF_A, s0_tbl);
rtw8922a_chlk_ktbl_sel(rtwdev, RF_B, s1_tbl);
}
static void rtw8922a_rfk_mlo_ctrl(struct rtw89_dev *rtwdev)
{
enum _rf_syn_pow syn_pow;
if (!rtwdev->dbcc_en)
goto set_rfk_reload;
switch (rtwdev->mlo_dbcc_mode) {
case MLO_0_PLUS_2_1RF:
syn_pow = RF_SYN_OFF_ON;
break;
case MLO_0_PLUS_2_2RF:
case MLO_1_PLUS_1_2RF:
case MLO_2_PLUS_0_1RF:
case MLO_2_PLUS_0_2RF:
case MLO_2_PLUS_2_2RF:
case MLO_DBCC_NOT_SUPPORT:
default:
syn_pow = RF_SYN_ON_OFF;
break;
case MLO_1_PLUS_1_1RF:
case DBCC_LEGACY:
syn_pow = RF_SYN_ALLON;
break;
}
rtw8922a_set_syn01(rtwdev, syn_pow);
set_rfk_reload:
rtw8922a_chlk_reload(rtwdev);
}
static void rtw8922a_rfk_pll_init(struct rtw89_dev *rtwdev)
{
int ret;
u8 tmp;
ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_PLL_1, &tmp);
if (ret)
return;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_PLL_1, tmp | 0xf8, 0xFF);
if (ret)
return;
ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_APBT, &tmp);
if (ret)
return;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_APBT, tmp & ~0x60, 0xFF);
if (ret)
return;
ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_XTAL_PLL, &tmp);
if (ret)
return;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_PLL, tmp | 0x38, 0xFF);
if (ret)
return;
}
void rtw8922a_rfk_hw_init(struct rtw89_dev *rtwdev)
{
if (rtwdev->dbcc_en)
rtw8922a_rfk_mlo_ctrl(rtwdev);
rtw8922a_rfk_pll_init(rtwdev);
}
void rtw8922a_pre_set_channel_rf(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
bool mlo_1_1;
if (!rtwdev->dbcc_en)
return;
mlo_1_1 = rtw89_is_mlo_1_1(rtwdev);
if (mlo_1_1)
rtw8922a_set_syn01(rtwdev, RF_SYN_ALLON);
else if (phy_idx == RTW89_PHY_0)
rtw8922a_set_syn01(rtwdev, RF_SYN_ON_OFF);
else
rtw8922a_set_syn01(rtwdev, RF_SYN_OFF_ON);
fsleep(1000);
}
void rtw8922a_post_set_channel_rf(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
rtw8922a_rfk_mlo_ctrl(rtwdev);
}

18
rtw8922a_rfk.h Normal file
View File

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2023 Realtek Corporation
*/
#ifndef __RTW89_8922A_RFK_H__
#define __RTW89_8922A_RFK_H__
#include "core.h"
void rtw8922a_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, u8 phy_idx);
void rtw8922a_set_channel_rf(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx);
void rtw8922a_rfk_hw_init(struct rtw89_dev *rtwdev);
void rtw8922a_pre_set_channel_rf(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void rtw8922a_post_set_channel_rf(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
#endif

91
rtw8922ae.c Normal file
View File

@ -0,0 +1,91 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2023 Realtek Corporation
*/
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
#include "reg.h"
#include "rtw8922a.h"
static const struct rtw89_pci_info rtw8922a_pci_info = {
.gen_def = &rtw89_pci_gen_be,
.txbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_trunc_mode = MAC_AX_BD_TRUNC,
.rxbd_mode = MAC_AX_RXBD_PKT,
.tag_mode = MAC_AX_TAG_MULTI,
.tx_burst = MAC_AX_TX_BURST_V1_256B,
.rx_burst = MAC_AX_RX_BURST_V1_128B,
.wd_dma_idle_intvl = MAC_AX_WD_DMA_INTVL_256NS,
.wd_dma_act_intvl = MAC_AX_WD_DMA_INTVL_256NS,
.multi_tag_num = MAC_AX_TAG_NUM_8,
.lbc_en = MAC_AX_PCIE_ENABLE,
.lbc_tmr = MAC_AX_LBC_TMR_2MS,
.autok_en = MAC_AX_PCIE_DISABLE,
.io_rcy_en = MAC_AX_PCIE_ENABLE,
.io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_DEF,
.rx_ring_eq_is_full = true,
.check_rx_tag = true,
.init_cfg_reg = R_BE_HAXI_INIT_CFG1,
.txhci_en_bit = B_BE_TXDMA_EN,
.rxhci_en_bit = B_BE_RXDMA_EN,
.rxbd_mode_bit = B_BE_RXQ_RXBD_MODE_MASK,
.exp_ctrl_reg = R_BE_HAXI_EXP_CTRL_V1,
.max_tag_num_mask = B_BE_MAX_TAG_NUM_MASK,
.rxbd_rwptr_clr_reg = R_BE_RXBD_RWPTR_CLR1_V1,
.txbd_rwptr_clr2_reg = R_BE_TXBD_RWPTR_CLR1,
.dma_io_stop = {R_BE_HAXI_INIT_CFG1, B_BE_STOP_AXI_MST},
.dma_stop1 = {R_BE_HAXI_DMA_STOP1, B_BE_TX_STOP1_MASK},
.dma_stop2 = {0},
.dma_busy1 = {R_BE_HAXI_DMA_BUSY1, DMA_BUSY1_CHECK_BE},
.dma_busy2_reg = 0,
.dma_busy3_reg = R_BE_HAXI_DMA_BUSY1,
.rpwm_addr = R_BE_PCIE_HRPWM,
.cpwm_addr = R_BE_PCIE_CRPWM,
.mit_addr = R_BE_PCIE_MIT_CH_EN,
.wp_sel_addr = R_BE_WP_ADDR_H_SEL0_3_V1,
.tx_dma_ch_mask = 0,
.bd_idx_addr_low_power = NULL,
.dma_addr_set = &rtw89_pci_ch_dma_addr_set_be,
.bd_ram_table = NULL,
.ltr_set = rtw89_pci_ltr_set_v2,
.fill_txaddr_info = rtw89_pci_fill_txaddr_info_v1,
.config_intr_mask = rtw89_pci_config_intr_mask_v2,
.enable_intr = rtw89_pci_enable_intr_v2,
.disable_intr = rtw89_pci_disable_intr_v2,
.recognize_intrs = rtw89_pci_recognize_intrs_v2,
};
static const struct rtw89_driver_info rtw89_8922ae_info = {
.chip = &rtw8922a_chip_info,
.quirks = NULL,
.bus = {
.pci = &rtw8922a_pci_info,
},
};
static const struct pci_device_id rtw89_8922ae_id_table[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8922),
.driver_data = (kernel_ulong_t)&rtw89_8922ae_info,
},
{},
};
MODULE_DEVICE_TABLE(pci, rtw89_8922ae_id_table);
static struct pci_driver rtw89_8922ae_driver = {
.name = "rtw89_8922ae",
.id_table = rtw89_8922ae_id_table,
.probe = rtw89_pci_probe,
.remove = rtw89_pci_remove,
.driver.pm = &rtw89_pm_ops_be,
};
module_pci_driver(rtw89_8922ae_driver);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11be wireless 8922AE driver");
MODULE_LICENSE("Dual BSD/GPL");

222
sar.c
View File

@ -2,9 +2,16 @@
/* Copyright(c) 2019-2020 Realtek Corporation
*/
#include "acpi.h"
#include "debug.h"
#include "phy.h"
#include "reg.h"
#include "sar.h"
#define RTW89_TAS_FACTOR 2 /* unit: 0.25 dBm */
#define RTW89_TAS_DPR_GAP (1 << RTW89_TAS_FACTOR)
#define RTW89_TAS_DELTA (2 << RTW89_TAS_FACTOR)
static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev,
u32 center_freq)
{
@ -78,17 +85,15 @@ static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = {
RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8),
};
static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg)
static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev,
u32 center_freq, s32 *cfg)
{
struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
enum rtw89_band band = chan->band_type;
u32 center_freq = chan->freq;
const struct rtw89_sar_span *span = NULL;
enum rtw89_sar_subband subband_l, subband_h;
int idx;
if (band == RTW89_BAND_6G) {
if (center_freq >= RTW89_SAR_6GHZ_SPAN_HEAD) {
idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq);
/* To decrease size of rtw89_sar_overlapping_6ghz[],
* RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs
@ -108,8 +113,8 @@ static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg)
}
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"for {band %u, center_freq %u}, SAR subband: {%u, %u}\n",
band, center_freq, subband_l, subband_h);
"center_freq %u: SAR subband {%u, %u}\n",
center_freq, subband_l, subband_h);
if (!rtwsar->set[subband_l] && !rtwsar->set[subband_h])
return -ENODATA;
@ -157,11 +162,35 @@ static s8 rtw89_txpwr_sar_to_mac(struct rtw89_dev *rtwdev, u8 fct, s32 cfg)
RTW89_SAR_TXPWR_MAC_MAX);
}
s8 rtw89_query_sar(struct rtw89_dev *rtwdev)
static s8 rtw89_txpwr_tas_to_sar(const struct rtw89_sar_handler *sar_hdl,
s8 cfg)
{
const u8 fct = sar_hdl->txpwr_factor_sar;
if (fct > RTW89_TAS_FACTOR)
return cfg << (fct - RTW89_TAS_FACTOR);
else
return cfg >> (RTW89_TAS_FACTOR - fct);
}
static s8 rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler *sar_hdl,
s8 cfg)
{
const u8 fct = sar_hdl->txpwr_factor_sar;
if (fct > RTW89_TAS_FACTOR)
return cfg >> (fct - RTW89_TAS_FACTOR);
else
return cfg << (RTW89_TAS_FACTOR - fct);
}
s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq)
{
const enum rtw89_sar_sources src = rtwdev->sar.src;
/* its members are protected by rtw89_sar_set_src() */
const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src];
struct rtw89_tas_info *tas = &rtwdev->tas;
s8 delta;
int ret;
s32 cfg;
u8 fct;
@ -171,16 +200,30 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev)
if (src == RTW89_SAR_SOURCE_NONE)
return RTW89_SAR_TXPWR_MAC_MAX;
ret = sar_hdl->query_sar_config(rtwdev, &cfg);
ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg);
if (ret)
return RTW89_SAR_TXPWR_MAC_MAX;
if (tas->enable) {
switch (tas->state) {
case RTW89_TAS_STATE_DPR_OFF:
return RTW89_SAR_TXPWR_MAC_MAX;
case RTW89_TAS_STATE_DPR_ON:
delta = rtw89_txpwr_tas_to_sar(sar_hdl, tas->delta);
cfg -= delta;
break;
case RTW89_TAS_STATE_DPR_FORBID:
default:
break;
}
}
fct = sar_hdl->txpwr_factor_sar;
return rtw89_txpwr_sar_to_mac(rtwdev, fct, cfg);
}
void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev)
void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev, u32 center_freq)
{
const enum rtw89_sar_sources src = rtwdev->sar.src;
/* its members are protected by rtw89_sar_set_src() */
@ -199,7 +242,7 @@ void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev)
seq_printf(m, "source: %d (%s)\n", src, sar_hdl->descr_sar_source);
ret = sar_hdl->query_sar_config(rtwdev, &cfg);
ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg);
if (ret) {
seq_printf(m, "config: return code: %d\n", ret);
seq_printf(m, "assign: max setting: %d (unit: 1/%lu dBm)\n",
@ -212,6 +255,19 @@ void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev)
seq_printf(m, "config: %d (unit: 1/%lu dBm)\n", cfg, BIT(fct));
}
void rtw89_print_tas(struct seq_file *m, struct rtw89_dev *rtwdev)
{
struct rtw89_tas_info *tas = &rtwdev->tas;
if (!tas->enable) {
seq_puts(m, "no TAS is applied\n");
return;
}
seq_printf(m, "DPR gap: %d\n", tas->dpr_gap);
seq_printf(m, "TAS delta: %d\n", tas->delta);
}
static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev,
const struct rtw89_sar_cfg_common *sar)
{
@ -292,3 +348,147 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
return rtw89_apply_sar_common(rtwdev, &sar_common);
}
static void rtw89_tas_state_update(struct rtw89_dev *rtwdev)
{
const enum rtw89_sar_sources src = rtwdev->sar.src;
/* its members are protected by rtw89_sar_set_src() */
const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src];
struct rtw89_tas_info *tas = &rtwdev->tas;
s32 txpwr_avg = tas->total_txpwr / RTW89_TAS_MAX_WINDOW / PERCENT;
s32 dpr_on_threshold, dpr_off_threshold, cfg;
enum rtw89_tas_state state = tas->state;
const struct rtw89_chan *chan;
int ret;
lockdep_assert_held(&rtwdev->mutex);
if (src == RTW89_SAR_SOURCE_NONE)
return;
chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
ret = sar_hdl->query_sar_config(rtwdev, chan->freq, &cfg);
if (ret)
return;
cfg = rtw89_txpwr_sar_to_tas(sar_hdl, cfg);
if (tas->delta >= cfg) {
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"TAS delta exceed SAR limit\n");
state = RTW89_TAS_STATE_DPR_FORBID;
goto out;
}
dpr_on_threshold = cfg;
dpr_off_threshold = cfg - tas->dpr_gap;
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"DPR_ON thold: %d, DPR_OFF thold: %d, txpwr_avg: %d\n",
dpr_on_threshold, dpr_off_threshold, txpwr_avg);
if (txpwr_avg >= dpr_on_threshold)
state = RTW89_TAS_STATE_DPR_ON;
else if (txpwr_avg < dpr_off_threshold)
state = RTW89_TAS_STATE_DPR_OFF;
out:
if (tas->state == state)
return;
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"TAS old state: %d, new state: %d\n", tas->state, state);
tas->state = state;
rtw89_core_set_chip_txpwr(rtwdev);
}
void rtw89_tas_init(struct rtw89_dev *rtwdev)
{
struct rtw89_tas_info *tas = &rtwdev->tas;
struct rtw89_acpi_dsm_result res = {};
int ret;
u8 val;
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_TAS_EN, &res);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"acpi: cannot get TAS: %d\n", ret);
return;
}
val = res.u.value;
switch (val) {
case 0:
tas->enable = false;
break;
case 1:
tas->enable = true;
break;
default:
break;
}
if (!tas->enable) {
rtw89_debug(rtwdev, RTW89_DBG_SAR, "TAS not enable\n");
return;
}
tas->dpr_gap = RTW89_TAS_DPR_GAP;
tas->delta = RTW89_TAS_DELTA;
}
void rtw89_tas_reset(struct rtw89_dev *rtwdev)
{
struct rtw89_tas_info *tas = &rtwdev->tas;
if (!tas->enable)
return;
memset(&tas->txpwr_history, 0, sizeof(tas->txpwr_history));
tas->total_txpwr = 0;
tas->cur_idx = 0;
tas->state = RTW89_TAS_STATE_DPR_OFF;
}
static const struct rtw89_reg_def txpwr_regs[] = {
{R_PATH0_TXPWR, B_PATH0_TXPWR},
{R_PATH1_TXPWR, B_PATH1_TXPWR},
};
void rtw89_tas_track(struct rtw89_dev *rtwdev)
{
struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
const enum rtw89_sar_sources src = rtwdev->sar.src;
u8 max_nss_num = rtwdev->chip->rf_path_num;
struct rtw89_tas_info *tas = &rtwdev->tas;
s16 tmp, txpwr, instant_txpwr = 0;
u32 val;
int i;
if (!tas->enable || src == RTW89_SAR_SOURCE_NONE)
return;
if (env->ccx_watchdog_result != RTW89_PHY_ENV_MON_IFS_CLM)
return;
for (i = 0; i < max_nss_num; i++) {
val = rtw89_phy_read32_mask(rtwdev, txpwr_regs[i].addr,
txpwr_regs[i].mask);
tmp = sign_extend32(val, 8);
if (tmp <= 0)
return;
instant_txpwr += tmp;
}
instant_txpwr /= max_nss_num;
/* in unit of 0.25 dBm multiply by percentage */
txpwr = instant_txpwr * env->ifs_clm_tx_ratio;
tas->total_txpwr += txpwr - tas->txpwr_history[tas->cur_idx];
tas->txpwr_history[tas->cur_idx] = txpwr;
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"instant_txpwr: %d, tx_ratio: %d, txpwr: %d\n",
instant_txpwr, env->ifs_clm_tx_ratio, txpwr);
tas->cur_idx = (tas->cur_idx + 1) % RTW89_TAS_MAX_WINDOW;
rtw89_tas_state_update(rtwdev);
}

14
sar.h
View File

@ -7,20 +7,24 @@
#include "core.h"
#define RTW89_SAR_TXPWR_MAC_MAX S8_MAX
#define RTW89_SAR_TXPWR_MAC_MIN S8_MIN
#define RTW89_SAR_TXPWR_MAC_MAX 63
#define RTW89_SAR_TXPWR_MAC_MIN -64
struct rtw89_sar_handler {
const char *descr_sar_source;
u8 txpwr_factor_sar;
int (*query_sar_config)(struct rtw89_dev *rtwdev, s32 *cfg);
int (*query_sar_config)(struct rtw89_dev *rtwdev, u32 center_freq, s32 *cfg);
};
extern const struct cfg80211_sar_capa rtw89_sar_capa;
s8 rtw89_query_sar(struct rtw89_dev *rtwdev);
void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev);
s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq);
void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev, u32 center_freq);
void rtw89_print_tas(struct seq_file *m, struct rtw89_dev *rtwdev);
int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar);
void rtw89_tas_init(struct rtw89_dev *rtwdev);
void rtw89_tas_reset(struct rtw89_dev *rtwdev);
void rtw89_tas_track(struct rtw89_dev *rtwdev);
#endif

44
ser.c
View File

@ -308,9 +308,13 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw89_vif *rtwvif = (struct rtw89_vif *)data;
struct rtw89_dev *rtwdev = rtwvif->rtwdev;
struct rtw89_vif *target_rtwvif = (struct rtw89_vif *)data;
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_dev *rtwdev = rtwvif->rtwdev;
if (rtwvif != target_rtwvif)
return;
if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls)
rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam);
@ -361,6 +365,9 @@ static int hal_enable_dma(struct rtw89_ser *ser)
ret = rtwdev->hci.ops->mac_lv1_rcvy(rtwdev, RTW89_LV1_RCVY_STEP_2);
if (!ret)
clear_bit(RTW89_SER_HAL_STOP_DMA, ser->flags);
else
rtw89_debug(rtwdev, RTW89_DBG_SER,
"lv1 rcvy fail to start dma: %d\n", ret);
return ret;
}
@ -376,6 +383,9 @@ static int hal_stop_dma(struct rtw89_ser *ser)
ret = rtwdev->hci.ops->mac_lv1_rcvy(rtwdev, RTW89_LV1_RCVY_STEP_1);
if (!ret)
set_bit(RTW89_SER_HAL_STOP_DMA, ser->flags);
else
rtw89_debug(rtwdev, RTW89_DBG_SER,
"lv1 rcvy fail to stop dma: %d\n", ret);
return ret;
}
@ -529,6 +539,9 @@ static void ser_do_hci_st_hdl(struct rtw89_ser *ser, u8 evt)
static void ser_mac_mem_dump(struct rtw89_dev *rtwdev, u8 *buf,
u8 sel, u32 start_addr, u32 len)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 filter_model_addr = mac->filter_model_addr;
u32 indir_access_addr = mac->indir_access_addr;
u32 *ptr = (u32 *)buf;
u32 base_addr, start_page, residue;
u32 cnt = 0;
@ -536,14 +549,14 @@ static void ser_mac_mem_dump(struct rtw89_dev *rtwdev, u8 *buf,
start_page = start_addr / MAC_MEM_DUMP_PAGE_SIZE;
residue = start_addr % MAC_MEM_DUMP_PAGE_SIZE;
base_addr = rtw89_mac_mem_base_addrs[sel];
base_addr = mac->mem_base_addrs[sel];
base_addr += start_page * MAC_MEM_DUMP_PAGE_SIZE;
while (cnt < len) {
rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, base_addr);
rtw89_write32(rtwdev, filter_model_addr, base_addr);
for (i = R_AX_INDIR_ACCESS_ENTRY + residue;
i < R_AX_INDIR_ACCESS_ENTRY + MAC_MEM_DUMP_PAGE_SIZE;
for (i = indir_access_addr + residue;
i < indir_access_addr + MAC_MEM_DUMP_PAGE_SIZE;
i += 4, ptr++) {
*ptr = rtw89_read32(rtwdev, i);
cnt += 4;
@ -581,11 +594,22 @@ struct __fw_backtrace_info {
static_assert(RTW89_FW_BACKTRACE_INFO_SIZE ==
sizeof(struct __fw_backtrace_info));
static u32 convert_addr_from_wcpu(u32 wcpu_addr)
{
if (wcpu_addr < 0x30000000)
return wcpu_addr;
return wcpu_addr & GENMASK(28, 0);
}
static int rtw89_ser_fw_backtrace_dump(struct rtw89_dev *rtwdev, u8 *buf,
const struct __fw_backtrace_entry *ent)
{
struct __fw_backtrace_info *ptr = (struct __fw_backtrace_info *)buf;
u32 fwbt_addr = ent->wcpu_addr & RTW89_WCPU_BASE_MASK;
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 filter_model_addr = mac->filter_model_addr;
u32 indir_access_addr = mac->indir_access_addr;
u32 fwbt_addr = convert_addr_from_wcpu(ent->wcpu_addr);
u32 fwbt_size = ent->size;
u32 fwbt_key = ent->key;
u32 i;
@ -610,10 +634,10 @@ static int rtw89_ser_fw_backtrace_dump(struct rtw89_dev *rtwdev, u8 *buf,
}
rtw89_debug(rtwdev, RTW89_DBG_SER, "dump fw backtrace start\n");
rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, fwbt_addr);
rtw89_write32(rtwdev, filter_model_addr, fwbt_addr);
for (i = R_AX_INDIR_ACCESS_ENTRY;
i < R_AX_INDIR_ACCESS_ENTRY + fwbt_size;
for (i = indir_access_addr;
i < indir_access_addr + fwbt_size;
i += RTW89_FW_BACKTRACE_INFO_SIZE, ptr++) {
*ptr = (struct __fw_backtrace_info){
.ra = rtw89_read32(rtwdev, i),

279
txrx.h
View File

@ -113,6 +113,8 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
#define RTW89_TXWD_INFO0_GI_LTF GENMASK(27, 25)
#define RTW89_TXWD_INFO0_DATA_RATE GENMASK(24, 16)
#define RTW89_TXWD_INFO0_DATA_ER BIT(15)
#define RTW89_TXWD_INFO0_DATA_STBC BIT(12)
#define RTW89_TXWD_INFO0_DATA_LDPC BIT(11)
#define RTW89_TXWD_INFO0_DISDATAFB BIT(10)
#define RTW89_TXWD_INFO0_DATA_BW_ER BIT(8)
#define RTW89_TXWD_INFO0_MULTIPORT_ID GENMASK(6, 4)
@ -137,6 +139,181 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
/* TX WD INFO DWORD 5 */
/* TX WD BODY DWORD 0 */
#define BE_TXD_BODY0_EN_HWSEQ_MODE GENMASK(1, 0)
#define BE_TXD_BODY0_HW_SSN_SEL GENMASK(4, 2)
#define BE_TXD_BODY0_HWAMSDU BIT(5)
#define BE_TXD_BODY0_HW_SEC_IV BIT(6)
#define BE_TXD_BODY0_WD_PAGE BIT(7)
#define BE_TXD_BODY0_CHK_EN BIT(8)
#define BE_TXD_BODY0_WP_INT BIT(9)
#define BE_TXD_BODY0_STF_MODE BIT(10)
#define BE_TXD_BODY0_HDR_LLC_LEN GENMASK(15, 11)
#define BE_TXD_BODY0_CH_DMA GENMASK(19, 16)
#define BE_TXD_BODY0_SMH_EN BIT(20)
#define BE_TXD_BODY0_PKT_OFFSET BIT(21)
#define BE_TXD_BODY0_WDINFO_EN BIT(22)
#define BE_TXD_BODY0_MOREDATA BIT(23)
#define BE_TXD_BODY0_WP_OFFSET_V1 GENMASK(27, 24)
#define BE_TXD_BODY0_AZ_FTM_SEC_V1 BIT(28)
#define BE_TXD_BODY0_WD_SOURCE GENMASK(30, 29)
#define BE_TXD_BODY0_HCI_SEQNUM_MODE BIT(31)
/* TX WD BODY DWORD 1 */
#define BE_TXD_BODY1_DMA_TXAGG_NUM GENMASK(6, 0)
#define BE_TXD_BODY1_REUSE_NUM GENMASK(11, 7)
#define BE_TXD_BODY1_SEC_TYPE GENMASK(15, 12)
#define BE_TXD_BODY1_SEC_KEYID GENMASK(17, 16)
#define BE_TXD_BODY1_SW_SEC_IV BIT(18)
#define BE_TXD_BODY1_REUSE_SIZE GENMASK(23, 20)
#define BE_TXD_BODY1_REUSE_START_OFFSET GENMASK(25, 24)
#define BE_TXD_BODY1_ADDR_INFO_NUM GENMASK(31, 26)
/* TX WD BODY DWORD 2 */
#define BE_TXD_BODY2_TXPKTSIZE GENMASK(13, 0)
#define BE_TXD_BODY2_AGG_EN BIT(14)
#define BE_TXD_BODY2_BK BIT(15)
#define BE_TXD_BODY2_MACID_EXTEND BIT(16)
#define BE_TXD_BODY2_QSEL GENMASK(22, 17)
#define BE_TXD_BODY2_TID_IND BIT(23)
#define BE_TXD_BODY2_MACID GENMASK(31, 24)
/* TX WD BODY DWORD 3 */
#define BE_TXD_BODY3_WIFI_SEQ GENMASK(11, 0)
#define BE_TXD_BODY3_MLO_FLAG BIT(12)
#define BE_TXD_BODY3_IS_MLD_SW_EN BIT(13)
#define BE_TXD_BODY3_TRY_RATE BIT(14)
#define BE_TXD_BODY3_RELINK_FLAG_V1 BIT(15)
#define BE_TXD_BODY3_BAND0_SU_TC_V1 GENMASK(21, 16)
#define BE_TXD_BODY3_TOTAL_TC GENMASK(27, 22)
#define BE_TXD_BODY3_RU_RTY BIT(28)
#define BE_TXD_BODY3_MU_PRI_RTY BIT(29)
#define BE_TXD_BODY3_MU_2ND_RTY BIT(30)
#define BE_TXD_BODY3_BAND1_SU_RTY_V1 BIT(31)
/* TX WD BODY DWORD 4 */
#define BE_TXD_BODY4_TXDESC_CHECKSUM GENMASK(15, 0)
#define BE_TXD_BODY4_SEC_IV_L0 GENMASK(23, 16)
#define BE_TXD_BODY4_SEC_IV_L1 GENMASK(31, 24)
/* TX WD BODY DWORD 5 */
#define BE_TXD_BODY5_SEC_IV_H2 GENMASK(7, 0)
#define BE_TXD_BODY5_SEC_IV_H3 GENMASK(15, 8)
#define BE_TXD_BODY5_SEC_IV_H4 GENMASK(23, 16)
#define BE_TXD_BODY5_SEC_IV_H5 GENMASK(31, 24)
/* TX WD BODY DWORD 6 */
#define BE_TXD_BODY6_MU_TC GENMASK(4, 0)
#define BE_TXD_BODY6_RU_TC GENMASK(9, 5)
#define BE_TXD_BODY6_PS160 BIT(10)
#define BE_TXD_BODY6_BMC BIT(11)
#define BE_TXD_BODY6_NO_ACK BIT(12)
#define BE_TXD_BODY6_UPD_WLAN_HDR BIT(13)
#define BE_TXD_BODY6_A4_HDR BIT(14)
#define BE_TXD_BODY6_EOSP_BIT BIT(15)
#define BE_TXD_BODY6_S_IDX GENMASK(23, 16)
#define BE_TXD_BODY6_RU_POS GENMASK(31, 24)
/* TX WD BODY DWORD 7 */
#define BE_TXD_BODY7_RTS_TC GENMASK(5, 0)
#define BE_TXD_BODY7_MSDU_NUM GENMASK(9, 6)
#define BE_TXD_BODY7_DATA_ER BIT(10)
#define BE_TXD_BODY7_DATA_BW_ER BIT(11)
#define BE_TXD_BODY7_DATA_DCM BIT(12)
#define BE_TXD_BODY7_GI_LTF GENMASK(15, 13)
#define BE_TXD_BODY7_DATARATE GENMASK(27, 16)
#define BE_TXD_BODY7_DATA_BW GENMASK(30, 28)
#define BE_TXD_BODY7_USERATE_SEL BIT(31)
/* TX WD INFO DWORD 0 */
#define BE_TXD_INFO0_MBSSID GENMASK(3, 0)
#define BE_TXD_INFO0_MULTIPORT_ID GENMASK(6, 4)
#define BE_TXD_INFO0_DISRTSFB BIT(9)
#define BE_TXD_INFO0_DISDATAFB BIT(10)
#define BE_TXD_INFO0_DATA_LDPC BIT(11)
#define BE_TXD_INFO0_DATA_STBC BIT(12)
#define BE_TXD_INFO0_DATA_TXCNT_LMT GENMASK(21, 16)
#define BE_TXD_INFO0_DATA_TXCNT_LMT_SEL BIT(22)
#define BE_TXD_INFO0_RESP_PHYSTS_CSI_EN_V1 BIT(23)
#define BE_TXD_INFO0_RLS_TO_CPUIO BIT(30)
#define BE_TXD_INFO0_ACK_CH_INFO BIT(31)
/* TX WD INFO DWORD 1 */
#define BE_TXD_INFO1_MAX_AGG_NUM GENMASK(7, 0)
#define BE_TXD_INFO1_BCN_SRCH_SEQ GENMASK(9, 8)
#define BE_TXD_INFO1_NAVUSEHDR BIT(10)
#define BE_TXD_INFO1_A_CTRL_BQR BIT(12)
#define BE_TXD_INFO1_A_CTRL_BSR BIT(14)
#define BE_TXD_INFO1_A_CTRL_CAS BIT(15)
#define BE_TXD_INFO1_DATA_RTY_LOWEST_RATE GENMASK(27, 16)
#define BE_TXD_INFO1_SW_DEFINE GENMASK(31, 28)
/* TX WD INFO DWORD 2 */
#define BE_TXD_INFO2_SEC_CAM_IDX GENMASK(7, 0)
#define BE_TXD_INFO2_FORCE_KEY_EN BIT(8)
#define BE_TXD_INFO2_LIFETIME_SEL GENMASK(15, 13)
#define BE_TXD_INFO2_FORCE_TXOP BIT(17)
#define BE_TXD_INFO2_AMPDU_DENSITY GENMASK(20, 18)
#define BE_TXD_INFO2_LSIG_TXOP_EN BIT(21)
#define BE_TXD_INFO2_OBW_CTS2SELF_DUP_TYPE GENMASK(29, 26)
#define BE_TXD_INFO2_SPE_RPT_V1 BIT(30)
#define BE_TXD_INFO2_SIFS_TX_V1 BIT(31)
/* TX WD INFO DWORD 3 */
#define BE_TXD_INFO3_SPE_PKT GENMASK(3, 0)
#define BE_TXD_INFO3_SPE_PKT_TYPE GENMASK(7, 4)
#define BE_TXD_INFO3_CQI_SND BIT(8)
#define BE_TXD_INFO3_RTT_EN BIT(9)
#define BE_TXD_INFO3_HT_DATA_SND_V1 BIT(10)
#define BE_TXD_INFO3_BT_NULL BIT(11)
#define BE_TXD_INFO3_TRI_FRAME BIT(12)
#define BE_TXD_INFO3_NULL_0 BIT(13)
#define BE_TXD_INFO3_NULL_1 BIT(14)
#define BE_TXD_INFO3_RAW BIT(15)
#define BE_TXD_INFO3_GROUP_BIT_IE_OFFSET GENMASK(23, 16)
#define BE_TXD_INFO3_SIGNALING_TA_PKT_EN BIT(25)
#define BE_TXD_INFO3_BCNPKT_TSF_CTRL BIT(26)
#define BE_TXD_INFO3_SIGNALING_TA_PKT_SC GENMASK(30, 27)
#define BE_TXD_INFO3_FORCE_BSS_CLR BIT(31)
/* TX WD INFO DWORD 4 */
#define BE_TXD_INFO4_PUNCTURE_PATTERN GENMASK(15, 0)
#define BE_TXD_INFO4_PUNC_MODE GENMASK(17, 16)
#define BE_TXD_INFO4_SW_TX_OK_0 BIT(18)
#define BE_TXD_INFO4_SW_TX_OK_1 BIT(19)
#define BE_TXD_INFO4_SW_TX_PWR_DBM GENMASK(26, 23)
#define BE_TXD_INFO4_RTS_EN BIT(27)
#define BE_TXD_INFO4_CTS2SELF BIT(28)
#define BE_TXD_INFO4_CCA_RTS GENMASK(30, 29)
#define BE_TXD_INFO4_HW_RTS_EN BIT(31)
/* TX WD INFO DWORD 5 */
#define BE_TXD_INFO5_SR_RATE_V1 GENMASK(4, 0)
#define BE_TXD_INFO5_SR_EN_V1 BIT(5)
#define BE_TXD_INFO5_NDPA_DURATION GENMASK(31, 16)
/* TX WD INFO DWORD 6 */
#define BE_TXD_INFO6_UL_APEP_LEN GENMASK(11, 0)
#define BE_TXD_INFO6_UL_GI_LTF GENMASK(14, 12)
#define BE_TXD_INFO6_UL_DOPPLER BIT(15)
#define BE_TXD_INFO6_UL_STBC BIT(16)
#define BE_TXD_INFO6_UL_LENGTH_REF GENMASK(21, 18)
#define BE_TXD_INFO6_UL_RF_GAIN_IDX GENMASK(31, 22)
/* TX WD INFO DWORD 7 */
#define BE_TXD_INFO7_UL_FIXED_GAIN_EN BIT(0)
#define BE_TXD_INFO7_UL_PRI_EXP_RSSI_DBM GENMASK(7, 1)
#define BE_TXD_INFO7_ELNA_IDX BIT(8)
#define BE_TXD_INFO7_UL_APEP_UNIT GENMASK(10, 9)
#define BE_TXD_INFO7_UL_TRI_PAD GENMASK(13, 11)
#define BE_TXD_INFO7_UL_T_PE GENMASK(15, 14)
#define BE_TXD_INFO7_UL_EHT_USR_PRES BIT(16)
#define BE_TXD_INFO7_UL_HELTF_SYMBOL_NUM GENMASK(19, 17)
#define BE_TXD_INFO7_ULBW GENMASK(21, 20)
#define BE_TXD_INFO7_ULBW_EXT GENMASK(23, 22)
#define BE_TXD_INFO7_USE_WD_UL GENMASK(25, 24)
#define BE_TXD_INFO7_EXTEND_MODE_SEL GENMASK(31, 28)
/* RX WD dword0 */
#define AX_RXD_RPKT_LEN_MASK GENMASK(13, 0)
#define AX_RXD_SHIFT_MASK GENMASK(15, 14)
@ -241,8 +418,11 @@ struct rtw89_rxinfo {
} __packed;
#define RTW89_RXINFO_W0_USR_NUM GENMASK(3, 0)
#define RTW89_RXINFO_W0_USR_NUM_V1 GENMASK(4, 0)
#define RTW89_RXINFO_W0_FW_DEFINE GENMASK(15, 8)
#define RTW89_RXINFO_W0_PLCP_LEN_V1 GENMASK(23, 16)
#define RTW89_RXINFO_W0_LSIG_LEN GENMASK(27, 16)
#define RTW89_RXINFO_W0_INVALID_V1 BIT(27)
#define RTW89_RXINFO_W0_IS_TO_SELF BIT(28)
#define RTW89_RXINFO_W0_RX_CNT_VLD BIT(29)
#define RTW89_RXINFO_W0_LONG_RXD GENMASK(31, 30)
@ -255,6 +435,7 @@ struct rtw89_phy_sts_hdr {
} __packed;
#define RTW89_PHY_STS_HDR_W0_IE_MAP GENMASK(4, 0)
#define RTW89_PHY_STS_HDR_W0_VALID BIT(7)
#define RTW89_PHY_STS_HDR_W0_LEN GENMASK(15, 8)
#define RTW89_PHY_STS_HDR_W0_RSSI_AVG GENMASK(31, 24)
#define RTW89_PHY_STS_HDR_W1_RSSI_A GENMASK(7, 0)
@ -269,6 +450,102 @@ struct rtw89_phy_sts_iehdr {
#define RTW89_PHY_STS_IEHDR_TYPE GENMASK(4, 0)
#define RTW89_PHY_STS_IEHDR_LEN GENMASK(11, 5)
/* BE RXD dword0 */
#define BE_RXD_RPKT_LEN_MASK GENMASK(13, 0)
#define BE_RXD_SHIFT_MASK GENMASK(15, 14)
#define BE_RXD_DRV_INFO_SZ_MASK GENMASK(19, 18)
#define BE_RXD_HDR_CNV_SZ_MASK GENMASK(21, 20)
#define BE_RXD_PHY_RPT_SZ_MASK GENMASK(23, 22)
#define BE_RXD_RPKT_TYPE_MASK GENMASK(29, 24)
#define BE_RXD_BB_SEL BIT(30)
#define BE_RXD_LONG_RXD BIT(31)
/* BE RXD dword1 */
#define BE_RXD_PKT_ID_MASK GENMASK(11, 0)
#define BE_RXD_FWD_TARGET_MASK GENMASK(23, 16)
#define BE_RXD_BCN_FW_INFO_MASK GENMASK(25, 24)
#define BE_RXD_FW_RLS BIT(26)
/* BE RXD dword2 */
#define BE_RXD_MAC_ID_MASK GENMASK(7, 0)
#define BE_RXD_TYPE_MASK GENMASK(11, 10)
#define BE_RXD_LAST_MSDU BIT(12)
#define BE_RXD_AMSDU_CUT BIT(13)
#define BE_RXD_ADDR_CAM_VLD BIT(14)
#define BE_RXD_REORDER BIT(15)
#define BE_RXD_SEQ_MASK GENMASK(27, 16)
#define BE_RXD_TID_MASK GENMASK(31, 28)
/* BE RXD dword3 */
#define BE_RXD_SEC_TYPE_MASK GENMASK(3, 0)
#define BE_RXD_BIP_KEYID BIT(4)
#define BE_RXD_BIP_ENC BIT(5)
#define BE_RXD_CRC32_ERR BIT(6)
#define BE_RXD_ICV_ERR BIT(7)
#define BE_RXD_HW_DEC BIT(8)
#define BE_RXD_SW_DEC BIT(9)
#define BE_RXD_A1_MATCH BIT(10)
#define BE_RXD_AMPDU BIT(11)
#define BE_RXD_AMPDU_EOF BIT(12)
#define BE_RXD_AMSDU BIT(13)
#define BE_RXD_MC BIT(14)
#define BE_RXD_BC BIT(15)
#define BE_RXD_MD BIT(16)
#define BE_RXD_MF BIT(17)
#define BE_RXD_PWR BIT(18)
#define BE_RXD_QOS BIT(19)
#define BE_RXD_EOSP BIT(20)
#define BE_RXD_HTC BIT(21)
#define BE_RXD_QNULL BIT(22)
#define BE_RXD_A4_FRAME BIT(23)
#define BE_RXD_FRAG_MASK GENMASK(27, 24)
#define BE_RXD_GET_CH_INFO_V1_MASK GENMASK(31, 30)
/* BE RXD dword4 */
#define BE_RXD_PPDU_TYPE_MASK GENMASK(7, 0)
#define BE_RXD_PPDU_CNT_MASK GENMASK(10, 8)
#define BE_RXD_BW_MASK GENMASK(14, 12)
#define BE_RXD_RX_GI_LTF_MASK GENMASK(18, 16)
#define BE_RXD_RX_REORDER_FIELD_EN BIT(19)
#define BE_RXD_RX_DATARATE_MASK GENMASK(31, 20)
/* BE RXD dword5 */
#define BE_RXD_FREERUN_CNT_MASK GENMASK(31, 0)
/* BE RXD dword6 */
#define BE_RXD_ADDR_CAM_MASK GENMASK(7, 0)
#define BE_RXD_SR_EN BIT(13)
#define BE_RXD_NON_SRG_PPDU BIT(14)
#define BE_RXD_INTER_PPDU BIT(15)
#define BE_RXD_USER_ID_MASK GENMASK(21, 16)
#define BE_RXD_RX_STATISTICS BIT(22)
#define BE_RXD_SMART_ANT BIT(23)
#define BE_RXD_SEC_CAM_IDX_MASK GENMASK(31, 24)
/* BE RXD dword7 */
#define BE_RXD_PATTERN_IDX_MASK GENMASK(4, 0)
#define BE_RXD_MAGIC_WAKE BIT(5)
#define BE_RXD_UNICAST_WAKE BIT(6)
#define BE_RXD_PATTERN_WAKE BIT(7)
#define BE_RXD_RX_PL_MATCH BIT(8)
#define BE_RXD_RX_PL_ID_MASK GENMASK(15, 12)
#define BE_RXD_HDR_CNV BIT(16)
#define BE_RXD_NAT25_HIT BIT(17)
#define BE_RXD_IS_DA BIT(18)
#define BE_RXD_CHKSUM_OFFLOAD_EN BIT(19)
#define BE_RXD_RXSC_ENTRY_MASK GENMASK(22, 20)
#define BE_RXD_RXSC_HIT BIT(23)
#define BE_RXD_WITH_LLC BIT(24)
#define BE_RXD_RX_AGG_FIELD_EN BIT(25)
/* BE RXD dword8 */
#define BE_RXD_MAC_ADDR_MASK GENMASK(31, 0)
/* BE RXD dword9 */
#define BE_RXD_MAC_ADDR_H_MASK GENMASK(15, 0)
#define BE_RXD_HDR_OFFSET_MASK GENMASK(20, 16)
#define BE_RXD_WL_HD_IV_LEN_MASK GENMASK(26, 21)
struct rtw89_phy_sts_ie0 {
__le32 w0;
__le32 w1;
@ -281,6 +558,8 @@ struct rtw89_phy_sts_ie0 {
#define RTW89_PHY_STS_IE01_W2_AVG_SNR GENMASK(5, 0)
#define RTW89_PHY_STS_IE01_W2_EVM_MAX GENMASK(15, 8)
#define RTW89_PHY_STS_IE01_W2_EVM_MIN GENMASK(23, 16)
#define RTW89_PHY_STS_IE01_W2_LDPC BIT(28)
#define RTW89_PHY_STS_IE01_W2_STBC BIT(30)
enum rtw89_tx_channel {
RTW89_TXCH_ACH0 = 0,

106
util.c Normal file
View File

@ -0,0 +1,106 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2024 Realtek Corporation
*/
#include "util.h"
#define FRAC_ROWS 3
#define FRAC_ROW_MAX (FRAC_ROWS - 1)
#define NORM_ROW_MIN FRAC_ROWS
static const u32 db_invert_table[12][8] = {
/* rows 0~2 in unit of U(32,3) */
{10, 13, 16, 20, 25, 32, 40, 50},
{64, 80, 101, 128, 160, 201, 256, 318},
{401, 505, 635, 800, 1007, 1268, 1596, 2010},
/* rows 3~11 in unit of U(32,0) */
{316, 398, 501, 631, 794, 1000, 1259, 1585},
{1995, 2512, 3162, 3981, 5012, 6310, 7943, 10000},
{12589, 15849, 19953, 25119, 31623, 39811, 50119, 63098},
{79433, 100000, 125893, 158489, 199526, 251189, 316228, 398107},
{501187, 630957, 794328, 1000000, 1258925, 1584893, 1995262, 2511886},
{3162278, 3981072, 5011872, 6309573, 7943282, 1000000, 12589254,
15848932},
{19952623, 25118864, 31622777, 39810717, 50118723, 63095734, 79432823,
100000000},
{125892541, 158489319, 199526232, 251188643, 316227766, 398107171,
501187234, 630957345},
{794328235, 1000000000, 1258925412, 1584893192, 1995262315, 2511886432U,
3162277660U, 3981071706U},
};
u32 rtw89_linear_2_db(u64 val)
{
u8 i, j;
u32 dB;
for (i = 0; i < 12; i++) {
for (j = 0; j < 8; j++) {
if (i <= FRAC_ROW_MAX &&
(val << RTW89_LINEAR_FRAC_BITS) <= db_invert_table[i][j])
goto cnt;
else if (i > FRAC_ROW_MAX && val <= db_invert_table[i][j])
goto cnt;
}
}
return 96; /* maximum 96 dB */
cnt:
/* special cases */
if (j == 0 && i == 0)
goto end;
if (i == NORM_ROW_MIN && j == 0) {
if (db_invert_table[NORM_ROW_MIN][0] - val >
val - (db_invert_table[FRAC_ROW_MAX][7] >> RTW89_LINEAR_FRAC_BITS)) {
i = FRAC_ROW_MAX;
j = 7;
}
goto end;
}
if (i <= FRAC_ROW_MAX)
val <<= RTW89_LINEAR_FRAC_BITS;
/* compare difference to get precise dB */
if (j == 0) {
if (db_invert_table[i][j] - val >
val - db_invert_table[i - 1][7]) {
i--;
j = 7;
}
} else {
if (db_invert_table[i][j] - val >
val - db_invert_table[i][j - 1]) {
j--;
}
}
end:
dB = (i << 3) + j + 1;
return dB;
}
EXPORT_SYMBOL(rtw89_linear_2_db);
u64 rtw89_db_2_linear(u32 db)
{
u64 linear;
u8 i, j;
if (db > 96)
db = 96;
else if (db < 1)
return 1;
i = (db - 1) >> 3;
j = (db - 1) & 0x7;
linear = db_invert_table[i][j];
if (i >= NORM_ROW_MIN)
linear = linear << RTW89_LINEAR_FRAC_BITS;
return linear;
}
EXPORT_SYMBOL(rtw89_db_2_linear);

5
util.h
View File

@ -6,6 +6,8 @@
#include "core.h"
#define RTW89_LINEAR_FRAC_BITS 3
#define rtw89_iterate_vifs_bh(rtwdev, iterator, data) \
ieee80211_iterate_active_interfaces_atomic((rtwdev)->hw, \
IEEE80211_IFACE_ITER_NORMAL, iterator, data)
@ -55,4 +57,7 @@ static inline void ether_addr_copy_mask(u8 *dst, const u8 *src, u8 mask)
}
}
u32 rtw89_linear_2_db(u64 linear);
u64 rtw89_db_2_linear(u32 db);
#endif

787
wow.c
View File

@ -12,6 +12,668 @@
#include "util.h"
#include "wow.h"
void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
const u8 *rsn, *ies = mgmt->u.assoc_req.variable;
struct rtw89_rsn_ie *rsn_ie;
rsn = cfg80211_find_ie(WLAN_EID_RSN, ies, skb->len);
if (!rsn)
return;
rsn_ie = (struct rtw89_rsn_ie *)rsn;
rtw_wow->akm = rsn_ie->akm_cipher_suite.type;
}
#define RTW89_CIPHER_INFO_DEF(cipher) \
{WLAN_CIPHER_SUITE_ ## cipher, .fw_alg = RTW89_WOW_FW_ALG_ ## cipher, \
.len = WLAN_KEY_LEN_ ## cipher}
static const struct rtw89_cipher_info rtw89_cipher_info_defs[] = {
RTW89_CIPHER_INFO_DEF(WEP40),
RTW89_CIPHER_INFO_DEF(WEP104),
RTW89_CIPHER_INFO_DEF(TKIP),
RTW89_CIPHER_INFO_DEF(CCMP),
RTW89_CIPHER_INFO_DEF(GCMP),
RTW89_CIPHER_INFO_DEF(CCMP_256),
RTW89_CIPHER_INFO_DEF(GCMP_256),
RTW89_CIPHER_INFO_DEF(AES_CMAC),
};
#undef RTW89_CIPHER_INFO_DEF
static const
struct rtw89_cipher_info *rtw89_cipher_alg_recognize(u32 cipher)
{
const struct rtw89_cipher_info *cipher_info_defs;
int i;
for (i = 0; i < ARRAY_SIZE(rtw89_cipher_info_defs); i++) {
cipher_info_defs = &rtw89_cipher_info_defs[i];
if (cipher_info_defs->cipher == cipher)
return cipher_info_defs;
}
return NULL;
}
static int _pn_to_iv(struct rtw89_dev *rtwdev, struct ieee80211_key_conf *key,
u8 *iv, u64 pn, u8 key_idx)
{
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
iv[0] = u64_get_bits(pn, RTW89_KEY_PN_1);
iv[1] = (u64_get_bits(pn, RTW89_KEY_PN_1) | 0x20) & 0x7f;
iv[2] = u64_get_bits(pn, RTW89_KEY_PN_0);
break;
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP_256:
iv[0] = u64_get_bits(pn, RTW89_KEY_PN_0);
iv[1] = u64_get_bits(pn, RTW89_KEY_PN_1);
iv[2] = 0;
break;
default:
return -EINVAL;
}
iv[3] = BIT(5) | ((key_idx & 0x3) << 6);
iv[4] = u64_get_bits(pn, RTW89_KEY_PN_2);
iv[5] = u64_get_bits(pn, RTW89_KEY_PN_3);
iv[6] = u64_get_bits(pn, RTW89_KEY_PN_4);
iv[7] = u64_get_bits(pn, RTW89_KEY_PN_5);
return 0;
}
static int rtw89_rx_pn_to_iv(struct rtw89_dev *rtwdev,
struct ieee80211_key_conf *key,
u8 *iv)
{
struct ieee80211_key_seq seq;
int err;
u64 pn;
ieee80211_get_key_rx_seq(key, 0, &seq);
/* seq.ccmp.pn[] is BE order array */
pn = u64_encode_bits(seq.ccmp.pn[0], RTW89_KEY_PN_5) |
u64_encode_bits(seq.ccmp.pn[1], RTW89_KEY_PN_4) |
u64_encode_bits(seq.ccmp.pn[2], RTW89_KEY_PN_3) |
u64_encode_bits(seq.ccmp.pn[3], RTW89_KEY_PN_2) |
u64_encode_bits(seq.ccmp.pn[4], RTW89_KEY_PN_1) |
u64_encode_bits(seq.ccmp.pn[5], RTW89_KEY_PN_0);
err = _pn_to_iv(rtwdev, key, iv, pn, key->keyidx);
if (err)
return err;
rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%llx to iv-%*ph\n",
__func__, key->keyidx, pn, 8, iv);
return 0;
}
static int rtw89_tx_pn_to_iv(struct rtw89_dev *rtwdev,
struct ieee80211_key_conf *key,
u8 *iv)
{
int err;
u64 pn;
pn = atomic64_inc_return(&key->tx_pn);
err = _pn_to_iv(rtwdev, key, iv, pn, key->keyidx);
if (err)
return err;
rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%llx to iv-%*ph\n",
__func__, key->keyidx, pn, 8, iv);
return 0;
}
static int _iv_to_pn(struct rtw89_dev *rtwdev, u8 *iv, u64 *pn, u8 *key_id,
struct ieee80211_key_conf *key)
{
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
*pn = u64_encode_bits(iv[2], RTW89_KEY_PN_0) |
u64_encode_bits(iv[0], RTW89_KEY_PN_1);
break;
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP_256:
*pn = u64_encode_bits(iv[0], RTW89_KEY_PN_0) |
u64_encode_bits(iv[1], RTW89_KEY_PN_1);
break;
default:
return -EINVAL;
}
*pn |= u64_encode_bits(iv[4], RTW89_KEY_PN_2) |
u64_encode_bits(iv[5], RTW89_KEY_PN_3) |
u64_encode_bits(iv[6], RTW89_KEY_PN_4) |
u64_encode_bits(iv[7], RTW89_KEY_PN_5);
if (key_id)
*key_id = *(iv + 3) >> 6;
return 0;
}
static int rtw89_rx_iv_to_pn(struct rtw89_dev *rtwdev,
struct ieee80211_key_conf *key,
u8 *iv)
{
struct ieee80211_key_seq seq;
int err;
u64 pn;
err = _iv_to_pn(rtwdev, iv, &pn, NULL, key);
if (err)
return err;
/* seq.ccmp.pn[] is BE order array */
seq.ccmp.pn[0] = u64_get_bits(pn, RTW89_KEY_PN_5);
seq.ccmp.pn[1] = u64_get_bits(pn, RTW89_KEY_PN_4);
seq.ccmp.pn[2] = u64_get_bits(pn, RTW89_KEY_PN_3);
seq.ccmp.pn[3] = u64_get_bits(pn, RTW89_KEY_PN_2);
seq.ccmp.pn[4] = u64_get_bits(pn, RTW89_KEY_PN_1);
seq.ccmp.pn[5] = u64_get_bits(pn, RTW89_KEY_PN_0);
ieee80211_set_key_rx_seq(key, 0, &seq);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d iv-%*ph to pn-%*ph\n",
__func__, key->keyidx, 8, iv, 6, seq.ccmp.pn);
return 0;
}
static int rtw89_tx_iv_to_pn(struct rtw89_dev *rtwdev,
struct ieee80211_key_conf *key,
u8 *iv)
{
int err;
u64 pn;
err = _iv_to_pn(rtwdev, iv, &pn, NULL, key);
if (err)
return err;
atomic64_set(&key->tx_pn, pn);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d iv-%*ph to pn-%llx\n",
__func__, key->keyidx, 8, iv, pn);
return 0;
}
static int rtw89_rx_pn_get_pmf(struct rtw89_dev *rtwdev,
struct ieee80211_key_conf *key,
struct rtw89_wow_gtk_info *gtk_info)
{
struct ieee80211_key_seq seq;
u64 pn;
if (key->keyidx == 4)
memcpy(gtk_info->igtk[0], key->key, key->keylen);
else if (key->keyidx == 5)
memcpy(gtk_info->igtk[1], key->key, key->keylen);
else
return -EINVAL;
ieee80211_get_key_rx_seq(key, 0, &seq);
/* seq.ccmp.pn[] is BE order array */
pn = u64_encode_bits(seq.ccmp.pn[0], RTW89_KEY_PN_5) |
u64_encode_bits(seq.ccmp.pn[1], RTW89_KEY_PN_4) |
u64_encode_bits(seq.ccmp.pn[2], RTW89_KEY_PN_3) |
u64_encode_bits(seq.ccmp.pn[3], RTW89_KEY_PN_2) |
u64_encode_bits(seq.ccmp.pn[4], RTW89_KEY_PN_1) |
u64_encode_bits(seq.ccmp.pn[5], RTW89_KEY_PN_0);
gtk_info->ipn = cpu_to_le64(pn);
gtk_info->igtk_keyid = cpu_to_le32(key->keyidx);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%llx\n",
__func__, key->keyidx, pn);
return 0;
}
static int rtw89_rx_pn_set_pmf(struct rtw89_dev *rtwdev,
struct ieee80211_key_conf *key,
u64 pn)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
struct ieee80211_key_seq seq;
if (key->keyidx != aoac_rpt->igtk_key_id)
return 0;
/* seq.ccmp.pn[] is BE order array */
seq.ccmp.pn[0] = u64_get_bits(pn, RTW89_KEY_PN_5);
seq.ccmp.pn[1] = u64_get_bits(pn, RTW89_KEY_PN_4);
seq.ccmp.pn[2] = u64_get_bits(pn, RTW89_KEY_PN_3);
seq.ccmp.pn[3] = u64_get_bits(pn, RTW89_KEY_PN_2);
seq.ccmp.pn[4] = u64_get_bits(pn, RTW89_KEY_PN_1);
seq.ccmp.pn[5] = u64_get_bits(pn, RTW89_KEY_PN_0);
ieee80211_set_key_rx_seq(key, 0, &seq);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%*ph\n",
__func__, key->keyidx, 6, seq.ccmp.pn);
return 0;
}
static void rtw89_wow_get_key_info_iter(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
void *data)
{
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_key_info *key_info = &rtw_wow->key_info;
struct rtw89_wow_gtk_info *gtk_info = &rtw_wow->gtk_info;
const struct rtw89_cipher_info *cipher_info;
bool *err = data;
int ret;
cipher_info = rtw89_cipher_alg_recognize(key->cipher);
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP_256:
if (sta) {
ret = rtw89_tx_pn_to_iv(rtwdev, key,
key_info->ptk_tx_iv);
if (ret)
goto err;
ret = rtw89_rx_pn_to_iv(rtwdev, key,
key_info->ptk_rx_iv);
if (ret)
goto err;
rtw_wow->ptk_alg = cipher_info->fw_alg;
rtw_wow->ptk_keyidx = key->keyidx;
} else {
ret = rtw89_rx_pn_to_iv(rtwdev, key,
key_info->gtk_rx_iv[key->keyidx]);
if (ret)
goto err;
rtw_wow->gtk_alg = cipher_info->fw_alg;
key_info->gtk_keyidx = key->keyidx;
}
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
ret = rtw89_rx_pn_get_pmf(rtwdev, key, gtk_info);
if (ret)
goto err;
break;
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
/* WEP only set group key in mac80211, but fw need to set
* both of pairwise key and group key.
*/
rtw_wow->ptk_alg = cipher_info->fw_alg;
rtw_wow->ptk_keyidx = key->keyidx;
rtw_wow->gtk_alg = cipher_info->fw_alg;
key_info->gtk_keyidx = key->keyidx;
break;
default:
rtw89_debug(rtwdev, RTW89_DBG_WOW, "unsupport cipher %x\n",
key->cipher);
goto err;
}
return;
err:
*err = true;
}
static void rtw89_wow_set_key_info_iter(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
void *data)
{
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
struct rtw89_set_key_info_iter_data *iter_data = data;
bool update_tx_key_info = iter_data->rx_ready;
int ret;
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP_256:
if (sta && !update_tx_key_info) {
ret = rtw89_rx_iv_to_pn(rtwdev, key,
aoac_rpt->ptk_rx_iv);
if (ret)
goto err;
}
if (sta && update_tx_key_info) {
ret = rtw89_tx_iv_to_pn(rtwdev, key,
aoac_rpt->ptk_tx_iv);
if (ret)
goto err;
}
if (!sta && !update_tx_key_info) {
ret = rtw89_rx_iv_to_pn(rtwdev, key,
aoac_rpt->gtk_rx_iv[key->keyidx]);
if (ret)
goto err;
}
if (!sta && update_tx_key_info && aoac_rpt->rekey_ok)
iter_data->gtk_cipher = key->cipher;
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
if (update_tx_key_info) {
if (aoac_rpt->rekey_ok)
iter_data->igtk_cipher = key->cipher;
} else {
ret = rtw89_rx_pn_set_pmf(rtwdev, key,
aoac_rpt->igtk_ipn);
if (ret)
goto err;
}
break;
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
break;
default:
rtw89_debug(rtwdev, RTW89_DBG_WOW, "unsupport cipher %x\n",
key->cipher);
goto err;
}
return;
err:
iter_data->error = true;
}
static void rtw89_wow_key_clear(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
memset(&rtw_wow->aoac_rpt, 0, sizeof(rtw_wow->aoac_rpt));
memset(&rtw_wow->gtk_info, 0, sizeof(rtw_wow->gtk_info));
memset(&rtw_wow->key_info, 0, sizeof(rtw_wow->key_info));
rtw_wow->ptk_alg = 0;
rtw_wow->gtk_alg = 0;
}
static void rtw89_wow_construct_key_info(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_key_info *key_info = &rtw_wow->key_info;
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
bool err = false;
rcu_read_lock();
ieee80211_iter_keys_rcu(rtwdev->hw, wow_vif,
rtw89_wow_get_key_info_iter, &err);
rcu_read_unlock();
if (err) {
rtw89_wow_key_clear(rtwdev);
return;
}
key_info->valid_check = RTW89_WOW_VALID_CHECK;
key_info->symbol_check_en = RTW89_WOW_SYMBOL_CHK_PTK |
RTW89_WOW_SYMBOL_CHK_GTK;
}
static void rtw89_wow_debug_aoac_rpt(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
if (!rtw89_debug_is_enabled(rtwdev, RTW89_DBG_WOW))
return;
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] rpt_ver = %d\n",
aoac_rpt->rpt_ver);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] sec_type = %d\n",
aoac_rpt->sec_type);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] key_idx = %d\n",
aoac_rpt->key_idx);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] pattern_idx = %d\n",
aoac_rpt->pattern_idx);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] rekey_ok = %d\n",
aoac_rpt->rekey_ok);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] ptk_tx_iv = %*ph\n",
8, aoac_rpt->ptk_tx_iv);
rtw89_debug(rtwdev, RTW89_DBG_WOW,
"[aoac_rpt] eapol_key_replay_count = %*ph\n",
8, aoac_rpt->eapol_key_replay_count);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] ptk_rx_iv = %*ph\n",
8, aoac_rpt->ptk_rx_iv);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] gtk_rx_iv[0] = %*ph\n",
8, aoac_rpt->gtk_rx_iv[0]);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] gtk_rx_iv[1] = %*ph\n",
8, aoac_rpt->gtk_rx_iv[1]);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] gtk_rx_iv[2] = %*ph\n",
8, aoac_rpt->gtk_rx_iv[2]);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] gtk_rx_iv[3] = %*ph\n",
8, aoac_rpt->gtk_rx_iv[3]);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] igtk_key_id = %llu\n",
aoac_rpt->igtk_key_id);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] igtk_ipn = %llu\n",
aoac_rpt->igtk_ipn);
rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] igtk = %*ph\n",
32, aoac_rpt->igtk);
}
static int rtw89_wow_get_aoac_rpt_reg(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
struct rtw89_mac_c2h_info c2h_info = {};
struct rtw89_mac_h2c_info h2c_info = {};
u8 igtk_ipn[8];
u8 key_idx;
int ret;
h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_AOAC_RPT_1;
h2c_info.content_len = 2;
ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info);
if (ret)
return ret;
aoac_rpt->key_idx =
u32_get_bits(c2h_info.u.c2hreg[0], RTW89_C2HREG_AOAC_RPT_1_W0_KEY_IDX);
key_idx = aoac_rpt->key_idx;
aoac_rpt->gtk_rx_iv[key_idx][0] =
u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_1_W1_IV_0);
aoac_rpt->gtk_rx_iv[key_idx][1] =
u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_1_W1_IV_1);
aoac_rpt->gtk_rx_iv[key_idx][2] =
u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_1_W1_IV_2);
aoac_rpt->gtk_rx_iv[key_idx][3] =
u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_1_W1_IV_3);
aoac_rpt->gtk_rx_iv[key_idx][4] =
u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_1_W2_IV_4);
aoac_rpt->gtk_rx_iv[key_idx][5] =
u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_1_W2_IV_5);
aoac_rpt->gtk_rx_iv[key_idx][6] =
u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_1_W2_IV_6);
aoac_rpt->gtk_rx_iv[key_idx][7] =
u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_1_W2_IV_7);
aoac_rpt->ptk_rx_iv[0] =
u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_0);
aoac_rpt->ptk_rx_iv[1] =
u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_1);
aoac_rpt->ptk_rx_iv[2] =
u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_2);
aoac_rpt->ptk_rx_iv[3] =
u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_3);
h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_AOAC_RPT_2;
h2c_info.content_len = 2;
ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info);
if (ret)
return ret;
aoac_rpt->ptk_rx_iv[4] =
u32_get_bits(c2h_info.u.c2hreg[0], RTW89_C2HREG_AOAC_RPT_2_W0_PTK_IV_4);
aoac_rpt->ptk_rx_iv[5] =
u32_get_bits(c2h_info.u.c2hreg[0], RTW89_C2HREG_AOAC_RPT_2_W0_PTK_IV_5);
aoac_rpt->ptk_rx_iv[6] =
u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_2_W1_PTK_IV_6);
aoac_rpt->ptk_rx_iv[7] =
u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_2_W1_PTK_IV_7);
igtk_ipn[0] =
u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_2_W1_IGTK_IPN_IV_0);
igtk_ipn[1] =
u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_2_W1_IGTK_IPN_IV_1);
igtk_ipn[2] =
u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_2);
igtk_ipn[3] =
u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_3);
igtk_ipn[4] =
u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_4);
igtk_ipn[5] =
u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_5);
igtk_ipn[6] =
u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_6);
igtk_ipn[7] =
u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_7);
aoac_rpt->igtk_ipn = u64_encode_bits(igtk_ipn[0], RTW89_IGTK_IPN_0) |
u64_encode_bits(igtk_ipn[1], RTW89_IGTK_IPN_1) |
u64_encode_bits(igtk_ipn[2], RTW89_IGTK_IPN_2) |
u64_encode_bits(igtk_ipn[3], RTW89_IGTK_IPN_3) |
u64_encode_bits(igtk_ipn[4], RTW89_IGTK_IPN_4) |
u64_encode_bits(igtk_ipn[5], RTW89_IGTK_IPN_5) |
u64_encode_bits(igtk_ipn[6], RTW89_IGTK_IPN_6) |
u64_encode_bits(igtk_ipn[7], RTW89_IGTK_IPN_7);
return 0;
}
static int rtw89_wow_get_aoac_rpt(struct rtw89_dev *rtwdev, bool rx_ready)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
int ret;
if (!rtw_wow->ptk_alg)
return -EPERM;
if (!rx_ready) {
ret = rtw89_wow_get_aoac_rpt_reg(rtwdev);
if (ret) {
rtw89_err(rtwdev, "wow: failed to get aoac rpt by reg\n");
return ret;
}
} else {
ret = rtw89_fw_h2c_wow_request_aoac(rtwdev);
if (ret) {
rtw89_err(rtwdev, "wow: failed to get aoac rpt by pkt\n");
return ret;
}
}
rtw89_wow_debug_aoac_rpt(rtwdev);
return 0;
}
static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev,
u32 cipher, u8 keyidx, u8 *gtk)
{
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
const struct rtw89_cipher_info *cipher_info;
struct ieee80211_key_conf *rekey_conf;
struct ieee80211_key_conf *key;
u8 sz;
cipher_info = rtw89_cipher_alg_recognize(cipher);
sz = struct_size(rekey_conf, key, cipher_info->len);
rekey_conf = kmalloc(sz, GFP_KERNEL);
if (!rekey_conf)
return NULL;
rekey_conf->cipher = cipher;
rekey_conf->keyidx = keyidx;
rekey_conf->keylen = cipher_info->len;
memcpy(rekey_conf->key, gtk,
flex_array_size(rekey_conf, key, cipher_info->len));
/* ieee80211_gtk_rekey_add() will call set_key(), therefore we
* need to unlock mutex
*/
mutex_unlock(&rtwdev->mutex);
key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, -1);
mutex_lock(&rtwdev->mutex);
kfree(rekey_conf);
if (IS_ERR(key)) {
rtw89_err(rtwdev, "ieee80211_gtk_rekey_add failed\n");
return NULL;
}
return key;
}
static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready)
{
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
struct rtw89_set_key_info_iter_data data = {.error = false,
.rx_ready = rx_ready};
struct ieee80211_key_conf *key;
rcu_read_lock();
ieee80211_iter_keys_rcu(rtwdev->hw, wow_vif,
rtw89_wow_set_key_info_iter, &data);
rcu_read_unlock();
if (data.error) {
rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s error\n", __func__);
return;
}
if (!data.gtk_cipher)
return;
key = rtw89_wow_gtk_rekey(rtwdev, data.gtk_cipher, aoac_rpt->key_idx,
aoac_rpt->gtk);
if (!key)
return;
rtw89_rx_iv_to_pn(rtwdev, key,
aoac_rpt->gtk_rx_iv[key->keyidx]);
if (!data.igtk_cipher)
return;
key = rtw89_wow_gtk_rekey(rtwdev, data.igtk_cipher, aoac_rpt->igtk_key_id,
aoac_rpt->igtk);
if (!key)
return;
rtw89_rx_pn_set_pmf(rtwdev, key, aoac_rpt->igtk_ipn);
ieee80211_gtk_rekey_notify(wow_vif, wow_vif->bss_conf.bssid,
aoac_rpt->eapol_key_replay_count,
GFP_KERNEL);
}
static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev)
{
__rtw89_leave_ps_mode(rtwdev);
@ -40,50 +702,27 @@ static void rtw89_wow_leave_lps(struct rtw89_dev *rtwdev)
static int rtw89_wow_config_mac(struct rtw89_dev *rtwdev, bool enable_wow)
{
int ret;
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
if (enable_wow) {
ret = rtw89_mac_resize_ple_rx_quota(rtwdev, true);
if (ret) {
rtw89_err(rtwdev, "[ERR]patch rx qta %d\n", ret);
return ret;
}
rtw89_write32_set(rtwdev, R_AX_RX_FUNCTION_STOP, B_AX_HDR_RX_STOP);
rtw89_write32_clr(rtwdev, R_AX_RX_FLTR_OPT, B_AX_SNIFFER_MODE);
rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false);
rtw89_write32(rtwdev, R_AX_ACTION_FWD0, 0);
rtw89_write32(rtwdev, R_AX_ACTION_FWD1, 0);
rtw89_write32(rtwdev, R_AX_TF_FWD, 0);
rtw89_write32(rtwdev, R_AX_HW_RPT_FWD, 0);
} else {
ret = rtw89_mac_resize_ple_rx_quota(rtwdev, false);
if (ret) {
rtw89_err(rtwdev, "[ERR]patch rx qta %d\n", ret);
return ret;
}
rtw89_write32_clr(rtwdev, R_AX_RX_FUNCTION_STOP, B_AX_HDR_RX_STOP);
rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
rtw89_write32(rtwdev, R_AX_ACTION_FWD0, TRXCFG_MPDU_PROC_ACT_FRWD);
rtw89_write32(rtwdev, R_AX_TF_FWD, TRXCFG_MPDU_PROC_TF_FRWD);
}
return 0;
return mac->wow_config_mac(rtwdev, enable_wow);
}
static void rtw89_wow_set_rx_filter(struct rtw89_dev *rtwdev, bool enable)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
enum rtw89_mac_fwd_target fwd_target = enable ?
RTW89_FWD_DONT_CARE :
RTW89_FWD_TO_HOST;
rtw89_mac_typ_fltr_opt(rtwdev, RTW89_MGNT, fwd_target, RTW89_MAC_0);
rtw89_mac_typ_fltr_opt(rtwdev, RTW89_CTRL, fwd_target, RTW89_MAC_0);
rtw89_mac_typ_fltr_opt(rtwdev, RTW89_DATA, fwd_target, RTW89_MAC_0);
mac->typ_fltr_opt(rtwdev, RTW89_MGNT, fwd_target, RTW89_MAC_0);
mac->typ_fltr_opt(rtwdev, RTW89_CTRL, fwd_target, RTW89_MAC_0);
mac->typ_fltr_opt(rtwdev, RTW89_DATA, fwd_target, RTW89_MAC_0);
}
static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
{
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
struct cfg80211_wowlan_nd_info nd_info;
struct cfg80211_wowlan_wakeup wakeup = {
.pattern_idx = -1,
@ -91,13 +730,12 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
u32 wow_reason_reg;
u8 reason;
if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B)
wow_reason_reg = R_AX_C2HREG_DATA3 + 3;
if (RTW89_CHK_FW_FEATURE(WOW_REASON_V1, &rtwdev->fw))
wow_reason_reg = rtwdev->chip->wow_reason_reg[RTW89_WOW_REASON_V1];
else
wow_reason_reg = R_AX_C2HREG_DATA3_V1 + 3;
wow_reason_reg = rtwdev->chip->wow_reason_reg[RTW89_WOW_REASON_V0];
reason = rtw89_read8(rtwdev, wow_reason_reg);
switch (reason) {
case RTW89_WOW_RSN_RX_DEAUTH:
wakeup.disconnect = true;
@ -116,10 +754,7 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx gtk rekey\n");
break;
case RTW89_WOW_RSN_RX_PATTERN_MATCH:
/* Current firmware and driver don't report pattern index
* Use pattern_idx to 0 defaultly.
*/
wakeup.pattern_idx = 0;
wakeup.pattern_idx = aoac_rpt->pattern_idx;
rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx pattern match packet\n");
break;
case RTW89_WOW_RSN_RX_NLO:
@ -468,13 +1103,14 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow)
static int rtw89_wow_check_fw_status(struct rtw89_dev *rtwdev, bool wow_enable)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u8 polling;
int ret;
ret = read_poll_timeout_atomic(rtw89_read8_mask, polling,
wow_enable == !!polling,
50, 50000, false, rtwdev,
R_AX_WOW_CTRL, B_AX_WOW_WOWEN);
mac->wow_ctrl.addr, mac->wow_ctrl.mask);
if (ret)
rtw89_err(rtwdev, "failed to check wow status %s\n",
wow_enable ? "enabled" : "disabled");
@ -484,15 +1120,21 @@ static int rtw89_wow_check_fw_status(struct rtw89_dev *rtwdev, bool wow_enable)
static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
{
enum rtw89_fw_type fw_type = wow ? RTW89_FW_WOWLAN : RTW89_FW_NORMAL;
enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
const struct rtw89_chip_info *chip = rtwdev->chip;
bool include_bb = !!chip->bbmcu_nr;
bool disable_intr_for_dlfw = false;
struct ieee80211_sta *wow_sta;
struct rtw89_sta *rtwsta = NULL;
bool is_conn = true;
int ret;
rtw89_hci_disable_intr(rtwdev);
if (chip_id == RTL8852C || chip_id == RTL8922A)
disable_intr_for_dlfw = true;
wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid);
if (wow_sta)
@ -500,12 +1142,18 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
else
is_conn = false;
ret = rtw89_fw_download(rtwdev, fw_type);
if (disable_intr_for_dlfw)
rtw89_hci_disable_intr(rtwdev);
ret = rtw89_fw_download(rtwdev, fw_type, include_bb);
if (ret) {
rtw89_warn(rtwdev, "download fw failed\n");
return ret;
}
if (disable_intr_for_dlfw)
rtw89_hci_enable_intr(rtwdev);
rtw89_phy_init_rf_reg(rtwdev, true);
ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta,
@ -515,7 +1163,7 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
return ret;
}
ret = rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, wow_vif, wow_sta);
ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, wow_vif, wow_sta);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c assoc cmac tbl\n");
return ret;
@ -547,8 +1195,10 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, wow_vif);
}
if (chip_gen == RTW89_CHIP_BE)
rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, RTW89_PHY_0, 5);
rtw89_mac_hw_mgnt_sec(rtwdev, wow);
rtw89_hci_enable_intr(rtwdev);
return 0;
}
@ -562,7 +1212,7 @@ static int rtw89_wow_enable_trx_pre(struct rtw89_dev *rtwdev)
rtw89_mac_ptk_drop_by_band_and_wait(rtwdev, RTW89_MAC_0);
ret = rtw89_hci_poll_txdma_ch(rtwdev);
ret = rtw89_hci_poll_txdma_ch_idle(rtwdev);
if (ret) {
rtw89_err(rtwdev, "txdma ch busy\n");
return ret;
@ -585,7 +1235,7 @@ static int rtw89_wow_enable_trx_post(struct rtw89_dev *rtwdev)
rtw89_hci_disable_intr(rtwdev);
rtw89_hci_ctrl_trxhci(rtwdev, false);
ret = rtw89_hci_poll_txdma_ch(rtwdev);
ret = rtw89_hci_poll_txdma_ch_idle(rtwdev);
if (ret) {
rtw89_err(rtwdev, "failed to poll txdma ch idle pcie\n");
return ret;
@ -623,19 +1273,38 @@ static int rtw89_wow_disable_trx_pre(struct rtw89_dev *rtwdev)
rtw89_err(rtwdev, "failed to config mac\n");
return ret;
}
/* Before enabling interrupt, we need to get AOAC report by reg due to RX
* not enabled yet. Also, we need to sync RX related IV from firmware to
* mac80211 before receiving RX packets from driver.
* After enabling interrupt, we can get AOAC report from h2c and c2h, and
* can get TX IV and complete rekey info. We need to update TX related IV
* and new GTK info if rekey happened.
*/
ret = rtw89_wow_get_aoac_rpt(rtwdev, false);
if (!ret)
rtw89_wow_update_key_info(rtwdev, false);
rtw89_hci_enable_intr(rtwdev);
ret = rtw89_wow_get_aoac_rpt(rtwdev, true);
if (!ret)
rtw89_wow_update_key_info(rtwdev, true);
return 0;
}
static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct ieee80211_vif *vif = rtw_wow->wow_vif;
int ret;
ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
if (ret)
rtw89_err(rtwdev, "cfg ppdu status\n");
rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
return ret;
}
@ -646,6 +1315,7 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev)
int ret;
rtw89_wow_pattern_write(rtwdev);
rtw89_wow_construct_key_info(rtwdev);
ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, true);
if (ret) {
@ -659,6 +1329,16 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev)
goto out;
}
ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, true);
if (ret) {
rtw89_err(rtwdev, "wow: failed to enable GTK offload\n");
goto out;
}
ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, true);
if (ret)
rtw89_warn(rtwdev, "wow: failed to enable arp offload\n");
ret = rtw89_wow_cfg_wake(rtwdev, true);
if (ret) {
rtw89_err(rtwdev, "wow: failed to config wake\n");
@ -695,14 +1375,25 @@ static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev)
goto out;
}
ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, false);
if (ret) {
rtw89_err(rtwdev, "wow: failed to disable GTK offload\n");
goto out;
}
ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, false);
if (ret)
rtw89_warn(rtwdev, "wow: failed to disable arp offload\n");
rtw89_wow_key_clear(rtwdev);
rtw89_fw_release_general_pkt_list(rtwdev, true);
ret = rtw89_wow_cfg_wake(rtwdev, false);
if (ret) {
rtw89_err(rtwdev, "wow: failed to disable config wake\n");
goto out;
}
rtw89_fw_release_general_pkt_list(rtwdev, true);
ret = rtw89_wow_check_fw_status(rtwdev, false);
if (ret) {
rtw89_err(rtwdev, "wow: failed to check disable fw ready\n");

87
wow.h
View File

@ -5,6 +5,26 @@
#ifndef __RTW89_WOW_H__
#define __RTW89_WOW_H__
#define RTW89_KEY_PN_0 GENMASK_ULL(7, 0)
#define RTW89_KEY_PN_1 GENMASK_ULL(15, 8)
#define RTW89_KEY_PN_2 GENMASK_ULL(23, 16)
#define RTW89_KEY_PN_3 GENMASK_ULL(31, 24)
#define RTW89_KEY_PN_4 GENMASK_ULL(39, 32)
#define RTW89_KEY_PN_5 GENMASK_ULL(47, 40)
#define RTW89_IGTK_IPN_0 GENMASK_ULL(7, 0)
#define RTW89_IGTK_IPN_1 GENMASK_ULL(15, 8)
#define RTW89_IGTK_IPN_2 GENMASK_ULL(23, 16)
#define RTW89_IGTK_IPN_3 GENMASK_ULL(31, 24)
#define RTW89_IGTK_IPN_4 GENMASK_ULL(39, 32)
#define RTW89_IGTK_IPN_5 GENMASK_ULL(47, 40)
#define RTW89_IGTK_IPN_6 GENMASK_ULL(55, 48)
#define RTW89_IGTK_IPN_7 GENMASK_ULL(63, 56)
#define RTW89_WOW_VALID_CHECK 0xDD
#define RTW89_WOW_SYMBOL_CHK_PTK BIT(0)
#define RTW89_WOW_SYMBOL_CHK_GTK BIT(1)
enum rtw89_wake_reason {
RTW89_WOW_RSN_RX_PTK_REKEY = 0x1,
RTW89_WOW_RSN_RX_GTK_REKEY = 0x2,
@ -15,7 +35,74 @@ enum rtw89_wake_reason {
RTW89_WOW_RSN_RX_NLO = 0x55,
};
enum rtw89_fw_alg {
RTW89_WOW_FW_ALG_WEP40 = 0x1,
RTW89_WOW_FW_ALG_WEP104 = 0x2,
RTW89_WOW_FW_ALG_TKIP = 0x3,
RTW89_WOW_FW_ALG_CCMP = 0x6,
RTW89_WOW_FW_ALG_CCMP_256 = 0x7,
RTW89_WOW_FW_ALG_GCMP = 0x8,
RTW89_WOW_FW_ALG_GCMP_256 = 0x9,
RTW89_WOW_FW_ALG_AES_CMAC = 0xa,
};
struct rtw89_cipher_suite {
u8 oui[3];
u8 type;
} __packed;
struct rtw89_rsn_ie {
u8 tag_number;
u8 tag_length;
__le16 rsn_version;
struct rtw89_cipher_suite group_cipher_suite;
__le16 pairwise_cipher_suite_cnt;
struct rtw89_cipher_suite pairwise_cipher_suite;
__le16 akm_cipher_suite_cnt;
struct rtw89_cipher_suite akm_cipher_suite;
} __packed;
struct rtw89_cipher_info {
u32 cipher;
u8 fw_alg;
enum ieee80211_key_len len;
};
struct rtw89_set_key_info_iter_data {
u32 gtk_cipher;
u32 igtk_cipher;
bool rx_ready;
bool error;
};
static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
if (!(rtwdev->chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)))
return 0;
switch (rtw_wow->ptk_alg) {
case RTW89_WOW_FW_ALG_WEP40:
return 4;
case RTW89_WOW_FW_ALG_TKIP:
case RTW89_WOW_FW_ALG_CCMP:
case RTW89_WOW_FW_ALG_GCMP_256:
return 8;
default:
return 0;
}
}
#ifdef CONFIG_PM
int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan);
int rtw89_wow_resume(struct rtw89_dev *rtwdev);
void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb);
#else
static inline
void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb)
{
}
#endif
#endif