Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,21 @@
# SPDX-License-Identifier: BSD-3-Clause-Clear
config MT7996E
tristate "MediaTek MT7996 (PCIe) support"
select MT76_CONNAC_LIB
select WANT_DEV_COREDUMP
select RELAY
depends on MAC80211
depends on PCI
help
This adds support for MT7996-based PCIe wireless devices,
which support concurrent tri-band operation at 6GHz, 5GHz,
and 2.4GHz IEEE 802.11be 4x4:4SS 4096-QAM, 320MHz channels.
To compile this driver as a module, choose M here.
config MT7996_NPU
bool "MT7996 (PCIe) NPU support"
depends on MT7996E
depends on NET_AIROHA_NPU=y || MT76_CORE=NET_AIROHA_NPU
select MT76_NPU
default n
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: BSD-3-Clause-Clear
obj-$(CONFIG_MT7996E) += mt7996e.o
mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
debugfs.o mmio.o
mt7996e-$(CONFIG_MT7996_NPU) += npu.o
mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
@@ -0,0 +1,268 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/* Copyright (C) 2023 MediaTek Inc. */
#include <linux/devcoredump.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/utsname.h>
#include "coredump.h"
static bool coredump_memdump;
module_param(coredump_memdump, bool, 0644);
MODULE_PARM_DESC(coredump_memdump, "Optional ability to dump firmware memory");
static const struct mt7996_mem_region mt7996_mem_regions[] = {
{
.start = 0x00800000,
.len = 0x0004ffff,
.name = "ULM0",
},
{
.start = 0x00900000,
.len = 0x00037fff,
.name = "ULM1",
},
{
.start = 0x02200000,
.len = 0x0003ffff,
.name = "ULM2",
},
{
.start = 0x00400000,
.len = 0x00067fff,
.name = "SRAM",
},
{
.start = 0xe0000000,
.len = 0x0015ffff,
.name = "CRAM0",
},
{
.start = 0xe0160000,
.len = 0x0011bfff,
.name = "CRAM1",
},
};
const struct mt7996_mem_region*
mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
{
switch (mt76_chip(&dev->mt76)) {
case MT7996_DEVICE_ID:
case MT7996_DEVICE_ID_2:
*num = ARRAY_SIZE(mt7996_mem_regions);
return &mt7996_mem_regions[0];
default:
return NULL;
}
}
static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev)
{
const struct mt7996_mem_region *mem_region;
size_t size = 0;
u32 num;
int i;
mem_region = mt7996_coredump_get_mem_layout(dev, &num);
if (!mem_region)
return 0;
for (i = 0; i < num; i++) {
size += mem_region->len;
mem_region++;
}
/* reserve space for the headers */
size += num * sizeof(struct mt7996_mem_hdr);
/* make sure it is aligned 4 bytes for debug message print out */
size = ALIGN(size, 4);
return size;
}
struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
{
struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
lockdep_assert_held(&dev->dump_mutex);
if (coredump_memdump &&
!mt76_poll_msec(dev, MT_FW_DUMP_STATE, 0x3, 0x2, 500))
return NULL;
guid_gen(&crash_data->guid);
ktime_get_real_ts64(&crash_data->timestamp);
return crash_data;
}
static void
mt7996_coredump_fw_state(struct mt7996_dev *dev, struct mt7996_coredump *dump,
bool *exception)
{
u32 count;
count = mt76_rr(dev, MT_FW_ASSERT_CNT);
/* normal mode: driver can manually trigger assert for detail info */
if (!count)
strscpy(dump->fw_state, "normal", sizeof(dump->fw_state));
else
strscpy(dump->fw_state, "exception", sizeof(dump->fw_state));
*exception = !!count;
}
static void
mt7996_coredump_fw_stack(struct mt7996_dev *dev, struct mt7996_coredump *dump,
bool exception)
{
u32 oldest, i, idx;
strscpy(dump->pc_current, "program counter", sizeof(dump->pc_current));
/* 0: WM PC log output */
mt76_wr(dev, MT_CONN_DBG_CTL_OUT_SEL, 0);
/* choose 33th PC log buffer to read current PC index */
mt76_wr(dev, MT_CONN_DBG_CTL_PC_LOG_SEL, 0x3f);
/* read current PC */
dump->pc_stack[0] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG);
/* stop call stack record */
if (!exception) {
mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
}
oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_PC_CTRL,
GENMASK(20, 16)) + 2;
for (i = 0; i < 16; i++) {
idx = ((oldest + 2 * i + 1) % 32);
dump->pc_stack[i + 1] =
mt76_rr(dev, MT_MCU_WM_EXCP_PC_LOG + idx * 4);
}
oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_LR_CTRL,
GENMASK(20, 16)) + 2;
for (i = 0; i < 16; i++) {
idx = ((oldest + 2 * i + 1) % 32);
dump->lr_stack[i] =
mt76_rr(dev, MT_MCU_WM_EXCP_LR_LOG + idx * 4);
}
/* start call stack record */
if (!exception) {
mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
}
}
static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev)
{
struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
struct mt7996_coredump *dump;
struct mt7996_coredump_mem *dump_mem;
size_t len, sofar = 0, hdr_len = sizeof(*dump);
unsigned char *buf;
bool exception;
len = hdr_len;
if (coredump_memdump && crash_data->memdump_buf_len)
len += sizeof(*dump_mem) + crash_data->memdump_buf_len;
sofar += hdr_len;
/* this is going to get big when we start dumping memory and such,
* so go ahead and use vmalloc.
*/
buf = vzalloc(len);
if (!buf)
return NULL;
mutex_lock(&dev->dump_mutex);
dump = (struct mt7996_coredump *)(buf);
dump->len = len;
/* plain text */
strscpy(dump->magic, "mt76-crash-dump", sizeof(dump->magic));
strscpy(dump->kernel, init_utsname()->release, sizeof(dump->kernel));
strscpy(dump->fw_ver, dev->mt76.hw->wiphy->fw_version,
sizeof(dump->fw_ver));
guid_copy(&dump->guid, &crash_data->guid);
dump->tv_sec = crash_data->timestamp.tv_sec;
dump->tv_nsec = crash_data->timestamp.tv_nsec;
dump->device_id = mt76_chip(&dev->mt76);
mt7996_coredump_fw_state(dev, dump, &exception);
mt7996_coredump_fw_stack(dev, dump, exception);
/* gather memory content */
dump_mem = (struct mt7996_coredump_mem *)(buf + sofar);
dump_mem->len = crash_data->memdump_buf_len;
if (coredump_memdump && crash_data->memdump_buf_len)
memcpy(dump_mem->data, crash_data->memdump_buf,
crash_data->memdump_buf_len);
mutex_unlock(&dev->dump_mutex);
return dump;
}
int mt7996_coredump_submit(struct mt7996_dev *dev)
{
struct mt7996_coredump *dump;
dump = mt7996_coredump_build(dev);
if (!dump) {
dev_warn(dev->mt76.dev, "no crash dump data found\n");
return -ENODATA;
}
dev_coredumpv(dev->mt76.dev, dump, dump->len, GFP_KERNEL);
return 0;
}
int mt7996_coredump_register(struct mt7996_dev *dev)
{
struct mt7996_crash_data *crash_data;
crash_data = vzalloc(sizeof(*dev->coredump.crash_data));
if (!crash_data)
return -ENOMEM;
dev->coredump.crash_data = crash_data;
if (coredump_memdump) {
crash_data->memdump_buf_len = mt7996_coredump_get_mem_size(dev);
if (!crash_data->memdump_buf_len)
/* no memory content */
return 0;
crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len);
if (!crash_data->memdump_buf) {
vfree(crash_data);
return -ENOMEM;
}
}
return 0;
}
void mt7996_coredump_unregister(struct mt7996_dev *dev)
{
if (dev->coredump.crash_data->memdump_buf) {
vfree(dev->coredump.crash_data->memdump_buf);
dev->coredump.crash_data->memdump_buf = NULL;
dev->coredump.crash_data->memdump_buf_len = 0;
}
vfree(dev->coredump.crash_data);
dev->coredump.crash_data = NULL;
}
@@ -0,0 +1,97 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/* Copyright (C) 2023 MediaTek Inc. */
#ifndef _COREDUMP_H_
#define _COREDUMP_H_
#include "mt7996.h"
struct mt7996_coredump {
char magic[16];
u32 len;
guid_t guid;
/* time-of-day stamp */
u64 tv_sec;
/* time-of-day stamp, nano-seconds */
u64 tv_nsec;
/* kernel version */
char kernel[64];
/* firmware version */
char fw_ver[ETHTOOL_FWVERS_LEN];
u32 device_id;
/* exception state */
char fw_state[12];
/* program counters */
char pc_current[16];
u32 pc_stack[17];
/* link registers */
u32 lr_stack[16];
/* memory content */
u8 data[];
} __packed;
struct mt7996_coredump_mem {
u32 len;
u8 data[];
} __packed;
struct mt7996_mem_hdr {
u32 start;
u32 len;
u8 data[];
};
struct mt7996_mem_region {
u32 start;
size_t len;
const char *name;
};
#ifdef CONFIG_DEV_COREDUMP
const struct mt7996_mem_region *
mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num);
struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev);
int mt7996_coredump_submit(struct mt7996_dev *dev);
int mt7996_coredump_register(struct mt7996_dev *dev);
void mt7996_coredump_unregister(struct mt7996_dev *dev);
#else /* CONFIG_DEV_COREDUMP */
static inline const struct mt7996_mem_region *
mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
{
return NULL;
}
static inline int mt7996_coredump_submit(struct mt7996_dev *dev)
{
return 0;
}
static inline struct
mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
{
return NULL;
}
static inline int mt7996_coredump_register(struct mt7996_dev *dev)
{
return 0;
}
static inline void mt7996_coredump_unregister(struct mt7996_dev *dev)
{
}
#endif /* CONFIG_DEV_COREDUMP */
#endif /* _COREDUMP_H_ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,415 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (C) 2022 MediaTek Inc.
*/
#include <linux/firmware.h>
#include "mt7996.h"
#include "eeprom.h"
static int mt7996_check_eeprom(struct mt7996_dev *dev)
{
u8 *eeprom = dev->mt76.eeprom.data;
u16 val = get_unaligned_le16(eeprom);
switch (val) {
case MT7996_DEVICE_ID:
return is_mt7996(&dev->mt76) ? 0 : -EINVAL;
case MT7992_DEVICE_ID:
return is_mt7992(&dev->mt76) ? 0 : -EINVAL;
case MT7990_DEVICE_ID:
return is_mt7990(&dev->mt76) ? 0 : -EINVAL;
default:
return -EINVAL;
}
}
static char *mt7996_eeprom_name(struct mt7996_dev *dev)
{
switch (mt76_chip(&dev->mt76)) {
case MT7992_DEVICE_ID:
switch (dev->var.type) {
case MT7992_VAR_TYPE_23:
if (dev->var.fem == MT7996_FEM_INT)
return MT7992_EEPROM_DEFAULT_23_INT;
return MT7992_EEPROM_DEFAULT_23;
case MT7992_VAR_TYPE_24:
return MT7992_EEPROM_DEFAULT_24;
case MT7992_VAR_TYPE_44:
default:
if (dev->var.fem == MT7996_FEM_INT)
return MT7992_EEPROM_DEFAULT_INT;
if (dev->var.fem == MT7996_FEM_MIX)
return MT7992_EEPROM_DEFAULT_MIX;
return MT7992_EEPROM_DEFAULT;
}
case MT7990_DEVICE_ID:
if (dev->var.fem == MT7996_FEM_INT)
return MT7990_EEPROM_DEFAULT_INT;
return MT7990_EEPROM_DEFAULT;
case MT7996_DEVICE_ID:
default:
switch (dev->var.type) {
case MT7996_VAR_TYPE_233:
if (dev->var.fem == MT7996_FEM_INT)
return MT7996_EEPROM_DEFAULT_233_INT;
return MT7996_EEPROM_DEFAULT_233;
case MT7996_VAR_TYPE_444:
default:
if (dev->var.fem == MT7996_FEM_INT)
return MT7996_EEPROM_DEFAULT_INT;
return MT7996_EEPROM_DEFAULT;
}
}
}
static void
mt7996_eeprom_parse_stream(const u8 *eeprom, u8 band_idx, u8 *path,
u8 *rx_path, u8 *nss)
{
switch (band_idx) {
case MT_BAND1:
*path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND1,
eeprom[MT_EE_WIFI_CONF + 2]);
*rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND1,
eeprom[MT_EE_WIFI_CONF + 3]);
*nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND1,
eeprom[MT_EE_WIFI_CONF + 5]);
break;
case MT_BAND2:
*path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND2,
eeprom[MT_EE_WIFI_CONF + 2]);
*rx_path = FIELD_GET(MT_EE_WIFI_CONF4_RX_PATH_BAND2,
eeprom[MT_EE_WIFI_CONF + 4]);
*nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND2,
eeprom[MT_EE_WIFI_CONF + 5]);
break;
default:
*path = FIELD_GET(MT_EE_WIFI_CONF1_TX_PATH_BAND0,
eeprom[MT_EE_WIFI_CONF + 1]);
*rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND0,
eeprom[MT_EE_WIFI_CONF + 3]);
*nss = FIELD_GET(MT_EE_WIFI_CONF4_STREAM_NUM_BAND0,
eeprom[MT_EE_WIFI_CONF + 4]);
break;
}
}
static bool mt7996_eeprom_variant_valid(struct mt7996_dev *dev, const u8 *def)
{
#define FEM_INT 0
#define FEM_EXT 3
u8 *eeprom = dev->mt76.eeprom.data, fem[2];
int i;
for (i = 0; i < 2; i++)
fem[i] = u8_get_bits(eeprom[MT_EE_WIFI_CONF + 6 + i],
MT_EE_WIFI_PA_LNA_CONFIG);
if (dev->var.fem == MT7996_FEM_EXT &&
!(fem[0] == FEM_EXT && fem[1] == FEM_EXT))
return false;
else if (dev->var.fem == MT7996_FEM_INT &&
!(fem[0] == FEM_INT && fem[1] == FEM_INT))
return false;
else if (dev->var.fem == MT7996_FEM_MIX &&
!(fem[0] == FEM_INT && fem[1] == FEM_EXT))
return false;
for (i = 0; i < __MT_MAX_BAND; i++) {
u8 path, rx_path, nss;
u8 def_path, def_rx_path, def_nss;
if (!dev->mt76.phys[i])
continue;
mt7996_eeprom_parse_stream(eeprom, i, &path, &rx_path, &nss);
mt7996_eeprom_parse_stream(def, i, &def_path, &def_rx_path,
&def_nss);
if (path > def_path || rx_path > def_rx_path || nss > def_nss)
return false;
}
return true;
}
static int
mt7996_eeprom_check_or_use_default(struct mt7996_dev *dev, bool use_default)
{
u8 *eeprom = dev->mt76.eeprom.data;
const struct firmware *fw = NULL;
int ret;
ret = request_firmware(&fw, mt7996_eeprom_name(dev), dev->mt76.dev);
if (ret)
return ret;
if (!fw || !fw->data) {
dev_err(dev->mt76.dev, "Invalid default bin\n");
ret = -EINVAL;
goto out;
}
if (!use_default && mt7996_eeprom_variant_valid(dev, fw->data))
goto out;
dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
memcpy(eeprom, fw->data, MT7996_EEPROM_SIZE);
dev->eeprom_mode = EEPROM_MODE_DEFAULT_BIN;
out:
release_firmware(fw);
return ret;
}
static int mt7996_eeprom_load(struct mt7996_dev *dev)
{
u32 eeprom_blk_size, block_num;
bool use_default = false;
int ret, i;
ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
if (ret < 0)
return ret;
if (ret && !mt7996_check_eeprom(dev)) {
dev->eeprom_mode = EEPROM_MODE_FLASH;
goto out;
}
memset(dev->mt76.eeprom.data, 0, MT7996_EEPROM_SIZE);
if (mt7996_has_ext_eeprom(dev)) {
/* external eeprom mode */
dev->eeprom_mode = EEPROM_MODE_EXT;
eeprom_blk_size = MT7996_EXT_EEPROM_BLOCK_SIZE;
} else {
u8 free_block_num;
/* efuse mode */
dev->eeprom_mode = EEPROM_MODE_EFUSE;
eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
ret = mt7996_mcu_get_efuse_free_block(dev, &free_block_num);
if (ret < 0)
return ret;
/* efuse info isn't enough */
if (free_block_num >= 59) {
use_default = true;
goto out;
}
}
/* check if eeprom data from fw is valid */
if (mt7996_mcu_get_eeprom(dev, 0, NULL, eeprom_blk_size,
dev->eeprom_mode) ||
mt7996_check_eeprom(dev)) {
use_default = true;
goto out;
}
/* read eeprom data from fw */
block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);
for (i = 1; i < block_num; i++) {
u32 len = eeprom_blk_size;
if (i == block_num - 1)
len = MT7996_EEPROM_SIZE % eeprom_blk_size;
ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size,
NULL, len, dev->eeprom_mode);
if (ret && ret != -EINVAL) {
use_default = true;
goto out;
}
}
out:
return mt7996_eeprom_check_or_use_default(dev, use_default);
}
static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_phy *phy,
u8 *path, u8 *rx_path, u8 *nss)
{
#define MODE_HE_ONLY BIT(0)
#define WTBL_SIZE_GROUP GENMASK(31, 28)
#define STREAM_CAP(_offs) ((cap & (0x7 << (_offs))) >> (_offs))
struct mt7996_dev *dev = phy->dev;
u32 cap = 0;
int ret;
ret = mt7996_mcu_get_chip_config(dev, &cap);
if (ret)
return ret;
if (cap) {
u8 band_offs = phy->mt76->band_idx * 3;
dev->has_eht = !(cap & MODE_HE_ONLY);
dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP);
*nss = min_t(u8, *nss, STREAM_CAP(1 + band_offs));
*path = min_t(u8, *path, STREAM_CAP(10 + band_offs));
*rx_path = min_t(u8, *rx_path, STREAM_CAP(19 + band_offs));
}
if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4)
dev->wtbl_size_group = is_mt7996(&dev->mt76) ? 4 : 2;
return 0;
}
static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)
{
u8 *eeprom = phy->dev->mt76.eeprom.data;
u32 val = eeprom[MT_EE_WIFI_CONF];
int ret = 0;
switch (phy->mt76->band_idx) {
case MT_BAND1:
val = FIELD_GET(MT_EE_WIFI_CONF1_BAND_SEL, val);
break;
case MT_BAND2:
val = eeprom[MT_EE_WIFI_CONF + 1];
val = FIELD_GET(MT_EE_WIFI_CONF2_BAND_SEL, val);
break;
default:
val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
break;
}
switch (val) {
case MT_EE_BAND_SEL_2GHZ:
phy->mt76->cap.has_2ghz = true;
break;
case MT_EE_BAND_SEL_5GHZ:
phy->mt76->cap.has_5ghz = true;
break;
case MT_EE_BAND_SEL_6GHZ:
phy->mt76->cap.has_6ghz = true;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
{
u8 path, rx_path, nss, band_idx = phy->mt76->band_idx;
u8 *eeprom = dev->mt76.eeprom.data;
struct mt76_phy *mphy = phy->mt76;
int max_path = 5, max_nss = 4;
int ret;
mt7996_eeprom_parse_stream(eeprom, band_idx, &path, &rx_path, &nss);
ret = mt7996_eeprom_parse_efuse_hw_cap(phy, &path, &rx_path, &nss);
if (ret)
return ret;
if (!path || path > max_path)
path = max_path;
if (!nss || nss > max_nss)
nss = max_nss;
nss = min_t(u8, nss, path);
if (path != rx_path)
phy->has_aux_rx = true;
mphy->antenna_mask = BIT(nss) - 1;
phy->orig_antenna_mask = mphy->antenna_mask;
mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx];
phy->orig_chainmask = mphy->chainmask;
dev->chainmask |= mphy->chainmask;
if (band_idx < MT_BAND2)
dev->chainshift[band_idx + 1] = dev->chainshift[band_idx] +
hweight16(mphy->chainmask);
return mt7996_eeprom_parse_band_config(phy);
}
int mt7996_eeprom_init(struct mt7996_dev *dev)
{
int ret;
ret = mt7996_eeprom_load(dev);
if (ret < 0)
return ret;
ret = mt7996_eeprom_parse_hw_cap(dev, &dev->phy);
if (ret < 0)
return ret;
memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN);
return mt76_eeprom_override(&dev->mphy);
}
int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
struct ieee80211_channel *chan)
{
u8 *eeprom = dev->mt76.eeprom.data;
int target_power;
if (chan->band == NL80211_BAND_5GHZ)
target_power = eeprom[MT_EE_TX0_POWER_5G +
mt7996_get_channel_group_5g(chan->hw_value)];
else if (chan->band == NL80211_BAND_6GHZ)
target_power = eeprom[MT_EE_TX0_POWER_6G +
mt7996_get_channel_group_6g(chan->hw_value)];
else
target_power = eeprom[MT_EE_TX0_POWER_2G];
return target_power;
}
s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
{
u8 *eeprom = dev->mt76.eeprom.data;
u32 val;
s8 delta;
if (band == NL80211_BAND_5GHZ)
val = eeprom[MT_EE_RATE_DELTA_5G];
else if (band == NL80211_BAND_6GHZ)
val = eeprom[MT_EE_RATE_DELTA_6G];
else
val = eeprom[MT_EE_RATE_DELTA_2G];
if (!(val & MT_EE_RATE_DELTA_EN))
return 0;
delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);
return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
}
bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev)
{
switch (mt76_chip(&dev->mt76)) {
case MT7996_DEVICE_ID:
if (dev->var.type == MT7996_VAR_TYPE_233)
return false;
break;
case MT7992_DEVICE_ID:
if (dev->var.type == MT7992_VAR_TYPE_23 ||
dev->var.type == MT7992_VAR_TYPE_24)
return false;
break;
case MT7990_DEVICE_ID: {
u8 path, rx_path, nss, *eeprom = dev->mt76.eeprom.data;
mt7996_eeprom_parse_stream(eeprom, MT_BAND1, &path, &rx_path, &nss);
/* Disable background radar capability in 3T3R */
if (path == 3 || rx_path == 3)
return false;
break;
}
default:
return false;
}
return true;
}
@@ -0,0 +1,79 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (C) 2022 MediaTek Inc.
*/
#ifndef __MT7996_EEPROM_H
#define __MT7996_EEPROM_H
#include "mt7996.h"
enum mt7996_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
MT_EE_MAC_ADDR = 0x004,
MT_EE_MAC_ADDR2 = 0x00a,
MT_EE_WIFI_CONF = 0x190,
MT_EE_MAC_ADDR3 = 0x2c0,
MT_EE_RATE_DELTA_2G = 0x1400,
MT_EE_RATE_DELTA_5G = 0x147d,
MT_EE_RATE_DELTA_6G = 0x154a,
MT_EE_TX0_POWER_2G = 0x1300,
MT_EE_TX0_POWER_5G = 0x1301,
MT_EE_TX0_POWER_6G = 0x1310,
__MT_EE_MAX = 0x1dff,
};
#define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
#define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(2, 0)
#define MT_EE_WIFI_CONF1_BAND_SEL GENMASK(5, 3)
#define MT_EE_WIFI_CONF2_BAND_SEL GENMASK(2, 0)
#define MT_EE_WIFI_CONF1_TX_PATH_BAND0 GENMASK(5, 3)
#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0)
#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3)
#define MT_EE_WIFI_CONF3_RX_PATH_BAND0 GENMASK(2, 0)
#define MT_EE_WIFI_CONF3_RX_PATH_BAND1 GENMASK(5, 3)
#define MT_EE_WIFI_CONF4_RX_PATH_BAND2 GENMASK(2, 0)
#define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0 GENMASK(5, 3)
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(2, 0)
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(5, 3)
#define MT_EE_WIFI_PA_LNA_CONFIG GENMASK(1, 0)
#define MT_EE_RATE_DELTA_MASK GENMASK(5, 0)
#define MT_EE_RATE_DELTA_SIGN BIT(6)
#define MT_EE_RATE_DELTA_EN BIT(7)
enum mt7996_eeprom_band {
MT_EE_BAND_SEL_DEFAULT,
MT_EE_BAND_SEL_2GHZ,
MT_EE_BAND_SEL_5GHZ,
MT_EE_BAND_SEL_6GHZ,
};
static inline int
mt7996_get_channel_group_5g(int channel)
{
if (channel <= 64)
return 0;
if (channel <= 96)
return 1;
if (channel <= 128)
return 2;
if (channel <= 144)
return 3;
return 4;
}
static inline int
mt7996_get_channel_group_6g(int channel)
{
if (channel <= 29)
return 0;
return DIV_ROUND_UP(channel - 29, 32);
}
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,40 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (C) 2022 MediaTek Inc.
*/
#ifndef __MT7996_MAC_H
#define __MT7996_MAC_H
#include "../mt76_connac3_mac.h"
struct mt7996_dfs_pulse {
u32 max_width; /* us */
int max_pwr; /* dbm */
int min_pwr; /* dbm */
u32 min_stgr_pri; /* us */
u32 max_stgr_pri; /* us */
u32 min_cr_pri; /* us */
u32 max_cr_pri; /* us */
};
struct mt7996_dfs_pattern {
u8 enb;
u8 stgr;
u8 min_crpn;
u8 max_crpn;
u8 min_crpr;
u8 min_pw;
u32 min_pri;
u32 max_pri;
u8 max_pw;
u8 min_crbn;
u8 max_crbn;
u8 min_stgpn;
u8 max_stgpn;
u8 min_stgpr;
u8 rsv[2];
u32 min_stgpr_diff;
} __packed;
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,892 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (C) 2022 MediaTek Inc.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/rtnetlink.h>
#include "mt7996.h"
#include "mac.h"
#include "mcu.h"
#include "../trace.h"
#include "../dma.h"
static bool wed_enable;
module_param(wed_enable, bool, 0644);
static const struct __base mt7996_reg_base[] = {
[WF_AGG_BASE] = { { 0x820e2000, 0x820f2000, 0x830e2000 } },
[WF_ARB_BASE] = { { 0x820e3000, 0x820f3000, 0x830e3000 } },
[WF_TMAC_BASE] = { { 0x820e4000, 0x820f4000, 0x830e4000 } },
[WF_RMAC_BASE] = { { 0x820e5000, 0x820f5000, 0x830e5000 } },
[WF_DMA_BASE] = { { 0x820e7000, 0x820f7000, 0x830e7000 } },
[WF_WTBLOFF_BASE] = { { 0x820e9000, 0x820f9000, 0x830e9000 } },
[WF_ETBF_BASE] = { { 0x820ea000, 0x820fa000, 0x830ea000 } },
[WF_LPON_BASE] = { { 0x820eb000, 0x820fb000, 0x830eb000 } },
[WF_MIB_BASE] = { { 0x820ed000, 0x820fd000, 0x830ed000 } },
[WF_RATE_BASE] = { { 0x820ee000, 0x820fe000, 0x830ee000 } },
};
static const u32 mt7996_offs[] = {
[MIB_RVSR0] = 0x720,
[MIB_RVSR1] = 0x724,
[MIB_BTSCR5] = 0x788,
[MIB_BTSCR6] = 0x798,
[MIB_RSCR1] = 0x7ac,
[MIB_RSCR27] = 0x954,
[MIB_RSCR28] = 0x958,
[MIB_RSCR29] = 0x95c,
[MIB_RSCR30] = 0x960,
[MIB_RSCR31] = 0x964,
[MIB_RSCR33] = 0x96c,
[MIB_RSCR35] = 0x974,
[MIB_RSCR36] = 0x978,
[MIB_BSCR0] = 0x9cc,
[MIB_BSCR1] = 0x9d0,
[MIB_BSCR2] = 0x9d4,
[MIB_BSCR3] = 0x9d8,
[MIB_BSCR4] = 0x9dc,
[MIB_BSCR5] = 0x9e0,
[MIB_BSCR6] = 0x9e4,
[MIB_BSCR7] = 0x9e8,
[MIB_BSCR17] = 0xa10,
[MIB_TRDR1] = 0xa28,
[HIF_REMAP_L1] = 0x24,
[HIF_REMAP_BASE_L1] = 0x130000,
[HIF_REMAP_L2] = 0x1b4,
[HIF_REMAP_BASE_L2] = 0x1000,
[CBTOP1_PHY_END] = 0x77ffffff,
[INFRA_MCU_END] = 0x7c3fffff,
[WTBLON_WDUCR] = 0x370,
[WTBL_UPDATE] = 0x380,
[WTBL_ITCR] = 0x3b0,
[WTBL_ITCR0] = 0x3b8,
[WTBL_ITCR1] = 0x3bc,
};
static const u32 mt7992_offs[] = {
[MIB_RVSR0] = 0x760,
[MIB_RVSR1] = 0x764,
[MIB_BTSCR5] = 0x7c8,
[MIB_BTSCR6] = 0x7d8,
[MIB_RSCR1] = 0x7f0,
[MIB_RSCR27] = 0x998,
[MIB_RSCR28] = 0x99c,
[MIB_RSCR29] = 0x9a0,
[MIB_RSCR30] = 0x9a4,
[MIB_RSCR31] = 0x9a8,
[MIB_RSCR33] = 0x9b0,
[MIB_RSCR35] = 0x9b8,
[MIB_RSCR36] = 0x9bc,
[MIB_BSCR0] = 0xac8,
[MIB_BSCR1] = 0xacc,
[MIB_BSCR2] = 0xad0,
[MIB_BSCR3] = 0xad4,
[MIB_BSCR4] = 0xad8,
[MIB_BSCR5] = 0xadc,
[MIB_BSCR6] = 0xae0,
[MIB_BSCR7] = 0xae4,
[MIB_BSCR17] = 0xb0c,
[MIB_TRDR1] = 0xb24,
[HIF_REMAP_L1] = 0x8,
[HIF_REMAP_BASE_L1] = 0x40000,
[HIF_REMAP_L2] = 0x1b4,
[HIF_REMAP_BASE_L2] = 0x1000,
[CBTOP1_PHY_END] = 0x77ffffff,
[INFRA_MCU_END] = 0x7c3fffff,
[WTBLON_WDUCR] = 0x370,
[WTBL_UPDATE] = 0x380,
[WTBL_ITCR] = 0x3b0,
[WTBL_ITCR0] = 0x3b8,
[WTBL_ITCR1] = 0x3bc,
};
static const u32 mt7990_offs[] = {
[MIB_RVSR0] = 0x800,
[MIB_RVSR1] = 0x804,
[MIB_BTSCR5] = 0x868,
[MIB_BTSCR6] = 0x878,
[MIB_RSCR1] = 0x890,
[MIB_RSCR27] = 0xa38,
[MIB_RSCR28] = 0xa3c,
[MIB_RSCR29] = 0xa40,
[MIB_RSCR30] = 0xa44,
[MIB_RSCR31] = 0xa48,
[MIB_RSCR33] = 0xa50,
[MIB_RSCR35] = 0xa58,
[MIB_RSCR36] = 0xa5c,
[MIB_BSCR0] = 0xbb8,
[MIB_BSCR1] = 0xbbc,
[MIB_BSCR2] = 0xbc0,
[MIB_BSCR3] = 0xbc4,
[MIB_BSCR4] = 0xbc8,
[MIB_BSCR5] = 0xbcc,
[MIB_BSCR6] = 0xbd0,
[MIB_BSCR7] = 0xbd4,
[MIB_BSCR17] = 0xbfc,
[MIB_TRDR1] = 0xc14,
[HIF_REMAP_L1] = 0x8,
[HIF_REMAP_BASE_L1] = 0x40000,
[HIF_REMAP_L2] = 0x1b8,
[HIF_REMAP_BASE_L2] = 0x110000,
[CBTOP1_PHY_END] = 0x7fffffff,
[INFRA_MCU_END] = 0x7cffffff,
[WTBLON_WDUCR] = 0x400,
[WTBL_UPDATE] = 0x410,
[WTBL_ITCR] = 0x440,
[WTBL_ITCR0] = 0x448,
[WTBL_ITCR1] = 0x44c,
};
static const struct __map mt7996_reg_map[] = {
{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA_0 (PCIE0 MCU DMA0) */
{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA_1 (PCIE0 MCU DMA1) */
{ 0x56000000, 0x04000, 0x1000 }, /* WFDMA reserved */
{ 0x57000000, 0x05000, 0x1000 }, /* WFDMA MCU wrap CR */
{ 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
{ 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
{ 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
{ 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
{ 0x820cc000, 0x0e000, 0x1000 }, /* WF_UMAC_TOP (PP) */
{ 0x74030000, 0x10000, 0x1000 }, /* PCIe MAC */
{ 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
{ 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
{ 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
{ 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
{ 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
{ 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
{ 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
{ 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
{ 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
{ 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
{ 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
{ 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
{ 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
{ 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
{ 0x820ca000, 0x26000, 0x2000 }, /* WF_LMAC_TOP BN0 (WF_MUCOP) */
{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
{ 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */
{ 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */
{ 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */
{ 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
{ 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
{ 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
{ 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
{ 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
{ 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
{ 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
{ 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
{ 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
{ 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
{ 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
{ 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
{ 0x820cc000, 0xa5000, 0x2000 }, /* WF_LMAC_TOP BN1 (WF_MUCOP) */
{ 0x820c4000, 0xa8000, 0x4000 }, /* WF_LMAC_TOP BN1 (WF_MUCOP) */
{ 0x820b0000, 0xae000, 0x1000 }, /* [APB2] WFSYS_ON */
{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, wfdma */
{ 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */
{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
{ 0x0, 0x0, 0x0 }, /* imply end of search */
};
static const struct __map mt7990_reg_map[] = {
{0x54000000, 0x02000, 0x1000}, /* WFDMA_0 (PCIE0 MCU DMA0) */
{0x55000000, 0x03000, 0x1000}, /* WFDMA_1 (PCIE0 MCU DMA1) */
{0x56000000, 0x04000, 0x1000}, /* WFDMA_2 (Reserved) */
{0x57000000, 0x05000, 0x1000}, /* WFDMA_3 (MCU wrap CR) */
{0x58000000, 0x06000, 0x1000}, /* WFDMA_4 (PCIE1 MCU DMA0 (MEM_DMA)) */
{0x59000000, 0x07000, 0x1000}, /* WFDMA_5 (PCIE1 MCU DMA1) */
{0x820c0000, 0x08000, 0x4000}, /* WF_UMAC_TOP (PLE) */
{0x820c8000, 0x0c000, 0x2000}, /* WF_UMAC_TOP (PSE) */
{0x820cc000, 0x0e000, 0x2000}, /* WF_UMAC_TOP (PP) */
{0x820e0000, 0x20000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_CFG) */
{0x820e1000, 0x20400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_TRB) */
{0x820e2000, 0x20800, 0x0400}, /* WF_LMAC_TOP BN0 (WF_AGG) */
{0x820e3000, 0x20c00, 0x0400}, /* WF_LMAC_TOP BN0 (WF_ARB) */
{0x820e4000, 0x21000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_TMAC) */
{0x820e5000, 0x21400, 0x0800}, /* WF_LMAC_TOP BN0 (WF_RMAC) */
{0x820ce000, 0x21c00, 0x0200}, /* WF_LMAC_TOP (WF_SEC) */
{0x820e7000, 0x21e00, 0x0200}, /* WF_LMAC_TOP BN0 (WF_DMA) */
{0x820cf000, 0x22000, 0x1000}, /* WF_LMAC_TOP (WF_PF) */
{0x820e9000, 0x23400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
{0x820ea000, 0x24000, 0x0200}, /* WF_LMAC_TOP BN0 (WF_ETBF) */
{0x820eb000, 0x24200, 0x0400}, /* WF_LMAC_TOP BN0 (WF_LPON) */
{0x820ec000, 0x24600, 0x0200}, /* WF_LMAC_TOP BN0 (WF_INT) */
{0x820ed000, 0x24800, 0x0800}, /* WF_LMAC_TOP BN0 (WF_MIB) */
{0x820ca000, 0x26000, 0x2000}, /* WF_LMAC_TOP BN0 (WF_MUCOP) */
{0x820d0000, 0x30000, 0x10000}, /* WF_LMAC_TOP (WF_WTBLON) */
{0x00400000, 0x80000, 0x10000}, /* WF_MCU_SYSRAM */
{0x820f0000, 0xa0000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_CFG) */
{0x820f1000, 0xa0600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_TRB) */
{0x820f2000, 0xa0800, 0x0400}, /* WF_LMAC_TOP BN1 (WF_AGG) */
{0x820f3000, 0xa0c00, 0x0400}, /* WF_LMAC_TOP BN1 (WF_ARB) */
{0x820f4000, 0xa1000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_TMAC) */
{0x820f5000, 0xa1400, 0x0800}, /* WF_LMAC_TOP BN1 (WF_RMAC) */
{0x820f7000, 0xa1e00, 0x0200}, /* WF_LMAC_TOP BN1 (WF_DMA) */
{0x820f9000, 0xa3400, 0x0200}, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
{0x820fa000, 0xa4000, 0x0200}, /* WF_LMAC_TOP BN1 (WF_ETBF) */
{0x820fb000, 0xa4200, 0x0400}, /* WF_LMAC_TOP BN1 (WF_LPON) */
{0x820fc000, 0xa4600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_INT) */
{0x820fd000, 0xa4800, 0x0800}, /* WF_LMAC_TOP BN1 (WF_MIB) */
{0x820cc000, 0xa5000, 0x2000}, /* WF_LMAC_TOP BN1 (WF_MUCOP) */
{0x820c4000, 0xa8000, 0x4000}, /* WF_LMAC_TOP (WF_UWTBL) */
{0x81030000, 0xae000, 0x100}, /* WFSYS_AON part 1 */
{0x81031000, 0xae100, 0x100}, /* WFSYS_AON part 2 */
{0x81032000, 0xae200, 0x100}, /* WFSYS_AON part 3 */
{0x81033000, 0xae300, 0x100}, /* WFSYS_AON part 4 */
{0x81034000, 0xae400, 0x100}, /* WFSYS_AON part 5 */
{0x80020000, 0xb0000, 0x10000}, /* WF_TOP_MISC_OFF */
{0x81020000, 0xc0000, 0x10000}, /* WF_TOP_MISC_ON */
{0x81040000, 0x120000, 0x1000}, /* WF_MCU_CFG_ON */
{0x81050000, 0x121000, 0x1000}, /* WF_MCU_EINT */
{0x81060000, 0x122000, 0x1000}, /* WF_MCU_GPT */
{0x81070000, 0x123000, 0x1000}, /* WF_MCU_WDT */
{0x80010000, 0x124000, 0x1000}, /* WF_AXIDMA */
{0x7c020000, 0xd0000, 0x10000}, /* CONN_INFRA, wfdma for from CODA flow use */
{0x7c060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top for from CODA flow use */
{0x20020000, 0xd0000, 0x10000}, /* CONN_INFRA, wfdma */
{0x20060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */
{0x7c000000, 0xf0000, 0x10000}, /* CONN_INFRA */
{0x70020000, 0x1f0000, 0x9000}, /* PCIE remapping (AP2CONN) */
{0x0, 0x0, 0x0}, /* imply end of search */
};
static u32 mt7996_reg_map_l1(struct mt7996_dev *dev, u32 addr)
{
u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
u32 l1_mask, val;
if (is_mt7996(&dev->mt76)) {
l1_mask = MT_HIF_REMAP_L1_MASK_7996;
val = FIELD_PREP(MT_HIF_REMAP_L1_MASK_7996, base);
} else {
l1_mask = MT_HIF_REMAP_L1_MASK;
val = FIELD_PREP(MT_HIF_REMAP_L1_MASK, base);
}
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1, l1_mask, val);
/* use read to push write */
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
return MT_HIF_REMAP_BASE_L1 + offset;
}
static u32 mt7996_reg_map_l2(struct mt7996_dev *dev, u32 addr)
{
u32 offset, base, l2_mask, val;
if (is_mt7990(&dev->mt76)) {
offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET_7990, addr);
base = FIELD_GET(MT_HIF_REMAP_L2_BASE_7990, addr);
l2_mask = MT_HIF_REMAP_L2_MASK_7990;
val = FIELD_PREP(MT_HIF_REMAP_L2_MASK_7990, base);
} else {
offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr);
base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr);
l2_mask = MT_HIF_REMAP_L2_MASK;
val = FIELD_PREP(MT_HIF_REMAP_L2_MASK, base);
}
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2, l2_mask, val);
/* use read to push write */
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2);
return MT_HIF_REMAP_BASE_L2 + offset;
}
static u32 mt7996_reg_map_cbtop(struct mt7996_dev *dev, u32 addr)
{
u32 offset = FIELD_GET(MT_HIF_REMAP_CBTOP_OFFSET, addr);
u32 base = FIELD_GET(MT_HIF_REMAP_CBTOP_BASE, addr);
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_CBTOP,
MT_HIF_REMAP_CBTOP_MASK,
FIELD_PREP(MT_HIF_REMAP_CBTOP_MASK, base));
/* use read to push write */
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_CBTOP);
return MT_HIF_REMAP_BASE_CBTOP + offset;
}
static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
{
int i;
if (addr < 0x100000)
return addr;
for (i = 0; i < dev->reg.map_size; i++) {
u32 ofs;
if (addr < dev->reg.map[i].phys)
continue;
ofs = addr - dev->reg.map[i].phys;
if (ofs >= dev->reg.map[i].size)
continue;
return dev->reg.map[i].mapped + ofs;
}
return 0;
}
static u32 __mt7996_reg_remap_addr(struct mt7996_dev *dev, u32 addr)
{
if ((addr >= MT_INFRA_BASE && addr < MT_WFSYS0_PHY_START) ||
(addr >= MT_WFSYS0_PHY_START && addr < MT_WFSYS1_PHY_START) ||
(addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END))
return mt7996_reg_map_l1(dev, addr);
/* CONN_INFRA: covert to phyiscal addr and use layer 1 remap */
if (addr >= MT_INFRA_MCU_START && addr <= MT_INFRA_MCU_END) {
addr = addr - MT_INFRA_MCU_START + MT_INFRA_BASE;
return mt7996_reg_map_l1(dev, addr);
}
if (dev_is_pci(dev->mt76.dev) &&
((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) ||
addr >= MT_CBTOP2_PHY_START)) {
if (is_mt7990(&dev->mt76))
return mt7996_reg_map_cbtop(dev, addr);
return mt7996_reg_map_l1(dev, addr);
}
return mt7996_reg_map_l2(dev, addr);
}
void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
size_t len)
{
u32 addr = __mt7996_reg_addr(dev, offset);
if (addr) {
memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
return;
}
spin_lock_bh(&dev->reg_lock);
memcpy_fromio(buf, dev->mt76.mmio.regs +
__mt7996_reg_remap_addr(dev, offset), len);
spin_unlock_bh(&dev->reg_lock);
}
static u32 mt7996_rr(struct mt76_dev *mdev, u32 offset)
{
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
u32 addr = __mt7996_reg_addr(dev, offset), val;
if (addr)
return dev->bus_ops->rr(mdev, addr);
spin_lock_bh(&dev->reg_lock);
val = dev->bus_ops->rr(mdev, __mt7996_reg_remap_addr(dev, offset));
spin_unlock_bh(&dev->reg_lock);
return val;
}
static void mt7996_wr(struct mt76_dev *mdev, u32 offset, u32 val)
{
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
u32 addr = __mt7996_reg_addr(dev, offset);
if (addr) {
dev->bus_ops->wr(mdev, addr, val);
return;
}
spin_lock_bh(&dev->reg_lock);
dev->bus_ops->wr(mdev, __mt7996_reg_remap_addr(dev, offset), val);
spin_unlock_bh(&dev->reg_lock);
}
static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
{
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
u32 addr = __mt7996_reg_addr(dev, offset);
if (addr)
return dev->bus_ops->rmw(mdev, addr, mask, val);
spin_lock_bh(&dev->reg_lock);
val = dev->bus_ops->rmw(mdev, __mt7996_reg_remap_addr(dev, offset), mask, val);
spin_unlock_bh(&dev->reg_lock);
return val;
}
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed)
{
struct mt76_dev *mdev = container_of(wed, struct mt76_dev, mmio.wed);
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
struct mt76_phy *mphy = &dev->mphy;
int ret;
ASSERT_RTNL();
if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state))
return -EBUSY;
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_FROM_ETH,
mphy->band_idx);
if (ret)
goto out;
rtnl_unlock();
if (!wait_for_completion_timeout(&mdev->mmio.wed_reset, 20 * HZ)) {
dev_err(mdev->dev, "wed reset timeout\n");
ret = -ETIMEDOUT;
}
rtnl_lock();
out:
clear_bit(MT76_STATE_WED_RESET, &mphy->state);
return ret;
}
#endif
int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
bool hif2, int *irq)
{
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
struct pci_dev *pci_dev = pdev_ptr;
u32 hif1_ofs;
if (!wed_enable)
return 0;
dev->mt76.hwrro_mode = is_mt7996(&dev->mt76) ? MT76_HWRRO_V3
: MT76_HWRRO_V3_1;
hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
if (hif2)
wed = &dev->mt76.mmio.wed_hif2;
wed->wlan.pci_dev = pci_dev;
wed->wlan.bus_type = MTK_WED_BUS_PCIE;
wed->wlan.base = devm_ioremap(dev->mt76.dev,
pci_resource_start(pci_dev, 0),
pci_resource_len(pci_dev, 0));
if (!wed->wlan.base)
return -ENOMEM;
wed->wlan.phy_base = pci_resource_start(pci_dev, 0);
if (hif2) {
wed->wlan.wpdma_int = wed->wlan.phy_base +
MT_INT_PCIE1_SOURCE_CSR_EXT;
wed->wlan.wpdma_mask = wed->wlan.phy_base +
MT_INT_PCIE1_MASK_CSR;
wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs +
MT_TXQ_RING_BASE(0) +
MT7996_TXQ_BAND2 * MT_RING_SIZE;
if (mt7996_has_hwrro(dev)) {
if (is_mt7996(&dev->mt76)) {
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(0) +
MT7996_RXQ_TXFREE2 * MT_RING_SIZE;
} else {
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_BAND1_EXT) - 1;
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(0) +
MT7996_RXQ_MCU_WA_EXT * MT_RING_SIZE;
}
} else {
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(0) +
MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1;
}
wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG;
wed->wlan.wpdma_rx[0] = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(MT7996_RXQ_BAND2) +
MT7996_RXQ_BAND2 * MT_RING_SIZE;
wed->wlan.id = MT7996_DEVICE_ID_2;
wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
} else {
wed->wlan.hw_rro = mt7996_has_hwrro(dev);
wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
MT7996_TXQ_BAND0 * MT_RING_SIZE;
wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + MT_WFDMA0_GLO_CFG;
wed->wlan.wpdma_rx[0] = wed->wlan.phy_base +
MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
MT7996_RXQ_BAND0 * MT_RING_SIZE;
wed->wlan.wpdma_rx_rro[0] = wed->wlan.phy_base +
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND0) +
MT7996_RXQ_RRO_BAND0 * MT_RING_SIZE;
if (is_mt7996(&dev->mt76)) {
wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
} else {
wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND1) +
MT7996_RXQ_RRO_BAND1 * MT_RING_SIZE;
wed->wlan.wpdma_rx[1] = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(MT7996_RXQ_BAND1) +
MT7996_RXQ_BAND1 * MT_RING_SIZE;
}
wed->wlan.wpdma_rx_pg = wed->wlan.phy_base +
MT_RXQ_RING_BASE(MT7996_RXQ_MSDU_PG_BAND0) +
MT7996_RXQ_MSDU_PG_BAND0 * MT_RING_SIZE;
wed->wlan.rx_nbuf = 65536;
wed->wlan.rx_npkt = dev->hif2 ? 32768 : 24576;
wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);
wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
wed->wlan.rro_rx_tbit[0] = ffs(MT_INT_RX_DONE_RRO_BAND0) - 1;
if (is_mt7996(&dev->mt76)) {
wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
} else {
wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND1) - 1;
wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND1) - 1;
}
wed->wlan.rx_pg_tbit[0] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND0) - 1;
wed->wlan.rx_pg_tbit[1] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND1) - 1;
wed->wlan.rx_pg_tbit[2] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND2) - 1;
wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
if (is_mt7996(&dev->mt76)) {
if (mt7996_has_hwrro(dev)) {
wed->wlan.wpdma_txfree = wed->wlan.phy_base +
MT_RXQ_RING_BASE(0) +
MT7996_RXQ_TXFREE0 * MT_RING_SIZE;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1;
} else {
wed->wlan.wpdma_txfree = wed->wlan.phy_base +
MT_RXQ_RING_BASE(0) +
MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
}
} else {
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
}
dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt;
if (dev->hif2 && is_mt7992(&dev->mt76))
wed->wlan.id = 0x7992;
}
wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE;
wed->wlan.token_start = MT7996_TOKEN_SIZE - wed->wlan.nbuf;
wed->wlan.hif2 = hif2;
wed->wlan.amsdu_max_subframes = 8;
wed->wlan.amsdu_max_len = 1536;
wed->wlan.init_buf = mt7996_wed_init_buf;
wed->wlan.init_rx_buf = mt76_wed_init_rx_buf;
wed->wlan.release_rx_buf = mt76_wed_release_rx_buf;
wed->wlan.offload_enable = mt76_wed_offload_enable;
wed->wlan.offload_disable = mt76_wed_offload_disable;
if (!hif2) {
wed->wlan.reset = mt7996_mmio_wed_reset;
wed->wlan.reset_complete = mt76_wed_reset_complete;
}
if (mtk_wed_device_attach(wed)) {
dev->mt76.hwrro_mode = MT76_HWRRO_OFF;
return 0;
}
*irq = wed->irq;
dev->mt76.dma_dev = wed->dev;
return 1;
#else
return 0;
#endif
}
static int mt7996_mmio_init(struct mt76_dev *mdev,
void __iomem *mem_base,
u32 device_id)
{
struct mt76_bus_ops *bus_ops;
struct mt7996_dev *dev;
dev = container_of(mdev, struct mt7996_dev, mt76);
mt76_mmio_init(&dev->mt76, mem_base);
spin_lock_init(&dev->reg_lock);
switch (device_id) {
case MT7996_DEVICE_ID:
dev->reg.base = mt7996_reg_base;
dev->reg.offs_rev = mt7996_offs;
dev->reg.map = mt7996_reg_map;
dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map);
break;
case MT7992_DEVICE_ID:
dev->reg.base = mt7996_reg_base;
dev->reg.offs_rev = mt7992_offs;
dev->reg.map = mt7996_reg_map;
dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map);
break;
case MT7990_DEVICE_ID:
dev->reg.base = mt7996_reg_base;
dev->reg.offs_rev = mt7990_offs;
dev->reg.map = mt7990_reg_map;
dev->reg.map_size = ARRAY_SIZE(mt7990_reg_map);
break;
default:
return -EINVAL;
}
dev->bus_ops = dev->mt76.bus;
bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
GFP_KERNEL);
if (!bus_ops)
return -ENOMEM;
bus_ops->rr = mt7996_rr;
bus_ops->wr = mt7996_wr;
bus_ops->rmw = mt7996_rmw;
dev->mt76.bus = bus_ops;
mdev->rev = (device_id << 16) | (mt76_rr(dev, MT_HW_REV) & 0xff);
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
return 0;
}
void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
u32 clear, u32 set)
{
struct mt76_dev *mdev = &dev->mt76;
unsigned long flags;
spin_lock_irqsave(&mdev->mmio.irq_lock, flags);
mdev->mmio.irqmask &= ~clear;
mdev->mmio.irqmask |= set;
if (write_reg) {
if (mtk_wed_device_active(&mdev->mmio.wed)) {
mtk_wed_device_irq_set_mask(&mdev->mmio.wed,
mdev->mmio.irqmask);
if (mtk_wed_device_active(&mdev->mmio.wed_hif2)) {
mtk_wed_device_irq_set_mask(&mdev->mmio.wed_hif2,
mdev->mmio.irqmask);
}
} else {
mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
}
}
spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags);
}
static void mt7996_rx_poll_complete(struct mt76_dev *mdev,
enum mt76_rxq_id q)
{
if (q == MT_RXQ_NPU0 || q == MT_RXQ_NPU1) {
struct airoha_npu *npu;
npu = rcu_dereference(mdev->mmio.npu);
if (npu)
airoha_npu_wlan_enable_irq(npu, q - MT_RXQ_NPU0);
} else {
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev,
mt76);
mt7996_irq_enable(dev, MT_INT_RX(q));
}
}
/* TODO: support 2/4/6/8 MSI-X vectors */
static void mt7996_irq_tasklet(struct tasklet_struct *t)
{
struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2;
u32 i, intr, mask, intr1 = 0;
if (dev->hif2 && mtk_wed_device_active(wed_hif2)) {
mtk_wed_device_irq_set_mask(wed_hif2, 0);
intr1 = mtk_wed_device_irq_get(wed_hif2,
dev->mt76.mmio.irqmask);
if (intr1 & MT_INT_RX_TXFREE_EXT)
napi_schedule(&dev->mt76.napi[MT_RXQ_TXFREE_BAND2]);
if (intr1 & MT_INT_RX_DONE_BAND2_EXT)
napi_schedule(&dev->mt76.napi[MT_RXQ_BAND2]);
if (intr1 & MT_INT_RX_TXFREE_BAND1_EXT)
napi_schedule(&dev->mt76.napi[MT_RXQ_BAND1_WA]);
}
if (mtk_wed_device_active(wed)) {
mtk_wed_device_irq_set_mask(wed, 0);
intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask);
intr |= (intr1 & ~MT_INT_TX_RX_DONE_EXT);
} else {
mt76_wr(dev, MT_INT_MASK_CSR, 0);
if (dev->hif2)
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
intr &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
if (dev->hif2) {
intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
intr1 &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
intr |= intr1;
}
}
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
mask = intr & MT_INT_RX_DONE_ALL;
if (intr & MT_INT_TX_DONE_MCU)
mask |= MT_INT_TX_DONE_MCU;
mt7996_irq_disable(dev, mask);
if (intr & MT_INT_TX_DONE_MCU)
napi_schedule(&dev->mt76.tx_napi);
for (i = 0; i < __MT_RXQ_MAX; i++) {
if ((intr & MT_INT_RX(i)))
napi_schedule(&dev->mt76.napi[i]);
}
if (intr & MT_INT_MCU_CMD) {
u32 val = mt76_rr(dev, MT_MCU_CMD);
mt76_wr(dev, MT_MCU_CMD, val);
if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) {
dev->recovery.state = val;
mt7996_reset(dev);
}
}
}
irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
{
struct mt7996_dev *dev = dev_instance;
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed, 0);
else
mt76_wr(dev, MT_INT_MASK_CSR, 0);
if (dev->hif2) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed_hif2, 0);
else
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
}
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
tasklet_schedule(&dev->mt76.irq_tasklet);
return IRQ_HANDLED;
}
struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
void __iomem *mem_base, u32 device_id)
{
static const struct mt76_driver_ops drv_ops = {
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
.link_data_size = sizeof(struct mt7996_vif_link),
.drv_flags = MT_DRV_TXWI_NO_FREE |
MT_DRV_AMSDU_OFFLOAD |
MT_DRV_HW_MGMT_TXQ,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
.token_size = MT7996_TOKEN_SIZE,
.tx_prepare_skb = mt7996_tx_prepare_skb,
.tx_complete_skb = mt76_connac_tx_complete_skb,
.rx_skb = mt7996_queue_rx_skb,
.rx_check = mt7996_rx_check,
.rx_poll_complete = mt7996_rx_poll_complete,
.rx_rro_ind_process = mt7996_rro_rx_process,
.rx_rro_add_msdu_page = mt7996_rro_msdu_page_add,
.update_survey = mt7996_update_channel,
.set_channel = mt7996_set_channel,
.vif_link_add = mt7996_vif_link_add,
.vif_link_remove = mt7996_vif_link_remove,
};
struct mt7996_dev *dev;
struct mt76_dev *mdev;
int ret;
mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt7996_ops, &drv_ops);
if (!mdev)
return ERR_PTR(-ENOMEM);
dev = container_of(mdev, struct mt7996_dev, mt76);
ret = mt7996_mmio_init(mdev, mem_base, device_id);
if (ret)
goto error;
tasklet_setup(&mdev->irq_tasklet, mt7996_irq_tasklet);
mt76_wr(dev, MT_INT_MASK_CSR, 0);
return dev;
error:
mt76_free_device(&dev->mt76);
return ERR_PTR(ret);
}
static int __init mt7996_init(void)
{
int ret;
ret = pci_register_driver(&mt7996_hif_driver);
if (ret)
return ret;
ret = pci_register_driver(&mt7996_pci_driver);
if (ret)
pci_unregister_driver(&mt7996_hif_driver);
return ret;
}
static void __exit mt7996_exit(void)
{
pci_unregister_driver(&mt7996_pci_driver);
pci_unregister_driver(&mt7996_hif_driver);
}
module_init(mt7996_init);
module_exit(mt7996_exit);
MODULE_DESCRIPTION("MediaTek MT7996 MMIO helpers");
MODULE_LICENSE("Dual BSD/GPL");
@@ -0,0 +1,978 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (C) 2022 MediaTek Inc.
*/
#ifndef __MT7996_H
#define __MT7996_H
#include <linux/interrupt.h>
#include <linux/ktime.h>
#include "../mt76_connac.h"
#include "regs.h"
#define MT7996_MAX_RADIOS 3
#define MT7996_MAX_INTERFACES 19 /* per-band */
#define MT7996_MAX_WMM_SETS 4
#define MT7996_WTBL_BMC_SIZE (is_mt7996(&dev->mt76) ? 64 : 32)
#define MT7996_WTBL_RESERVED (mt7996_wtbl_size(dev) - 1)
#define MT7996_WTBL_STA (MT7996_WTBL_RESERVED - \
mt7996_max_interface_num(dev))
#define MT7996_WATCHDOG_TIME (HZ / 10)
#define MT7996_RESET_TIMEOUT (30 * HZ)
#define MT7996_TX_RING_SIZE 2048
#define MT7996_TX_MCU_RING_SIZE 256
#define MT7996_TX_FWDL_RING_SIZE 128
#define MT7996_RX_RING_SIZE 1536
#define MT7996_RX_MCU_RING_SIZE 512
#define MT7996_RX_MCU_RING_SIZE_WA 1024
#define MT7996_NPU_TX_RING_SIZE 1024
#define MT7996_NPU_RX_RING_SIZE 1024
#define MT7996_NPU_TXD_SIZE 3
/* scatter-gather of mcu event is not supported in connac3 */
#define MT7996_RX_MCU_BUF_SIZE (2048 + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
#define MT7996_DEVICE_ID 0x7990
#define MT7996_DEVICE_ID_2 0x7991
#define MT7992_DEVICE_ID 0x7992
#define MT7992_DEVICE_ID_2 0x799a
#define MT7990_DEVICE_ID 0x7993
#define MT7990_DEVICE_ID_2 0x799b
#define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
#define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
#define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin"
#define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin"
#define MT7996_FIRMWARE_WA_233 "mediatek/mt7996/mt7996_wa_233.bin"
#define MT7996_FIRMWARE_WM_233 "mediatek/mt7996/mt7996_wm_233.bin"
#define MT7996_FIRMWARE_DSP_233 MT7996_FIRMWARE_DSP
#define MT7996_ROM_PATCH_233 "mediatek/mt7996/mt7996_rom_patch_233.bin"
#define MT7992_FIRMWARE_WA "mediatek/mt7996/mt7992_wa.bin"
#define MT7992_FIRMWARE_WM "mediatek/mt7996/mt7992_wm.bin"
#define MT7992_FIRMWARE_DSP "mediatek/mt7996/mt7992_dsp.bin"
#define MT7992_ROM_PATCH "mediatek/mt7996/mt7992_rom_patch.bin"
#define MT7992_FIRMWARE_WA_23 "mediatek/mt7996/mt7992_wa_23.bin"
#define MT7992_FIRMWARE_WM_23 "mediatek/mt7996/mt7992_wm_23.bin"
#define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin"
#define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin"
#define MT7992_FIRMWARE_WA_24 "mediatek/mt7996/mt7992_wa_24.bin"
#define MT7992_FIRMWARE_WM_24 "mediatek/mt7996/mt7992_wm_24.bin"
#define MT7992_FIRMWARE_DSP_24 "mediatek/mt7996/mt7992_dsp_24.bin"
#define MT7992_ROM_PATCH_24 "mediatek/mt7996/mt7992_rom_patch_24.bin"
#define MT7990_FIRMWARE_WA ""
#define MT7990_FIRMWARE_WM "mediatek/mt7996/mt7990_wm.bin"
#define MT7990_FIRMWARE_DSP ""
#define MT7990_ROM_PATCH "mediatek/mt7996/mt7990_rom_patch.bin"
#define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
#define MT7996_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7996_eeprom_2i5i6i.bin"
#define MT7996_EEPROM_DEFAULT_233 "mediatek/mt7996/mt7996_eeprom_233.bin"
#define MT7996_EEPROM_DEFAULT_233_INT "mediatek/mt7996/mt7996_eeprom_233_2i5i6i.bin"
#define MT7992_EEPROM_DEFAULT "mediatek/mt7996/mt7992_eeprom.bin"
#define MT7992_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7992_eeprom_2i5i.bin"
#define MT7992_EEPROM_DEFAULT_MIX "mediatek/mt7996/mt7992_eeprom_2i5e.bin"
#define MT7992_EEPROM_DEFAULT_23 "mediatek/mt7996/mt7992_eeprom_23.bin"
#define MT7992_EEPROM_DEFAULT_23_INT "mediatek/mt7996/mt7992_eeprom_23_2i5i.bin"
#define MT7992_EEPROM_DEFAULT_24 "mediatek/mt7996/mt7992_eeprom_24_2i5i.bin"
#define MT7990_EEPROM_DEFAULT "mediatek/mt7996/mt7990_eeprom.bin"
#define MT7990_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7990_eeprom_2i5i.bin"
#define MT7996_EEPROM_SIZE 7680
#define MT7996_EEPROM_BLOCK_SIZE 16
#define MT7996_EXT_EEPROM_BLOCK_SIZE 1024
#define MT7996_TOKEN_SIZE 16384
#define MT7996_HW_TOKEN_SIZE 8192
#define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
#define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
#define MT7996_IBF_MAX_NC 2
#define MT7996_IBF_TIMEOUT 0x18
#define MT7996_IBF_TIMEOUT_LEGACY 0x48
#define MT7992_CFEND_RATE_DEFAULT 0x4b /* OFDM 6M */
#define MT7992_IBF_TIMEOUT 0xff
#define MT7996_SKU_RATE_NUM 417
#define MT7996_SKU_PATH_NUM 494
#define MT7996_MAX_TWT_AGRT 16
#define MT7996_MAX_STA_TWT_AGRT 8
#define MT7996_MIN_TWT_DUR 64
#define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
#define MT7996_BASIC_RATES_TBL 31
#define MT7996_BEACON_RATES_TBL 25
#define MT7996_THERMAL_THROTTLE_MAX 100
#define MT7996_CDEV_THROTTLE_MAX 99
#define MT7996_CRIT_TEMP_IDX 0
#define MT7996_MAX_TEMP_IDX 1
#define MT7996_CRIT_TEMP 110
#define MT7996_MAX_TEMP 120
#define MT7996_MAX_HIF_RXD_IN_PG 5
#define MT7996_RRO_MSDU_PG_HASH_SIZE 127
#define MT7996_RRO_MAX_SESSION 1024
#define MT7996_RRO_WINDOW_MAX_LEN 1024
#define MT7996_RRO_ADDR_ELEM_LEN 128
#define MT7996_RRO_BA_BITMAP_LEN 2
#define MT7996_RRO_BA_BITMAP_CR_SIZE ((MT7996_RRO_MAX_SESSION * 128) / \
MT7996_RRO_BA_BITMAP_LEN)
#define MT7996_RRO_BA_BITMAP_SESSION_SIZE (MT7996_RRO_MAX_SESSION / \
MT7996_RRO_ADDR_ELEM_LEN)
#define MT7996_RRO_WINDOW_MAX_SIZE (MT7996_RRO_WINDOW_MAX_LEN * \
MT7996_RRO_BA_BITMAP_SESSION_SIZE)
#define MT7996_RX_BUF_SIZE (1800 + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
#define MT7996_RX_MSDU_PAGE_SIZE (128 + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
/* RRO 3.1 */
#define MT7996_RRO_MSDU_PG_CR_CNT 8
#define MT7996_RRO_MSDU_PG_SIZE_PER_CR 0x10000
struct mt7996_vif;
struct mt7996_sta;
struct mt7996_dfs_pulse;
struct mt7996_dfs_pattern;
enum mt7996_ram_type {
MT7996_RAM_TYPE_WM,
MT7996_RAM_TYPE_WA,
MT7996_RAM_TYPE_DSP,
};
enum mt7996_var_type {
MT7996_VAR_TYPE_444,
MT7996_VAR_TYPE_233,
};
enum mt7992_var_type {
MT7992_VAR_TYPE_44,
MT7992_VAR_TYPE_23,
MT7992_VAR_TYPE_24,
};
enum mt7990_var_type {
MT7990_VAR_TYPE_23,
};
enum mt7996_fem_type {
MT7996_FEM_EXT,
MT7996_FEM_INT,
MT7996_FEM_MIX,
};
enum mt7996_eeprom_mode {
EEPROM_MODE_DEFAULT_BIN,
EEPROM_MODE_EFUSE,
EEPROM_MODE_FLASH,
EEPROM_MODE_EXT,
};
#define MT7996_EFUSE_BASE_OFFS_ADIE0 0x400
#define MT7996_EFUSE_BASE_OFFS_ADIE1 0x1e00
#define MT7996_EFUSE_BASE_OFFS_ADIE2 0x1200
#define MT7992_EFUSE_BASE_OFFS_ADIE1 0x1200
enum mt7996_txq_id {
MT7996_TXQ_FWDL = 16,
MT7996_TXQ_MCU_WM,
MT7996_TXQ_BAND0,
MT7996_TXQ_BAND1,
MT7996_TXQ_MCU_WA,
MT7996_TXQ_BAND2,
};
enum mt7996_rxq_id {
MT7996_RXQ_MCU_WM = 0,
MT7996_RXQ_MCU_WA,
MT7996_RXQ_MCU_WA_MAIN = 2,
MT7996_RXQ_MCU_WA_EXT = 3, /* for mt7992 */
MT7996_RXQ_MCU_WA_TRI = 3,
MT7996_RXQ_BAND0 = 4,
MT7996_RXQ_BAND1 = 5, /* for mt7992 */
MT7996_RXQ_BAND2 = 5,
MT7996_RXQ_RRO_BAND0 = 8,
MT7996_RXQ_RRO_BAND1 = 9,
MT7996_RXQ_RRO_BAND2 = 6,
MT7996_RXQ_MSDU_PG_BAND0 = 10,
MT7996_RXQ_MSDU_PG_BAND1 = 11,
MT7996_RXQ_MSDU_PG_BAND2 = 12,
MT7996_RXQ_TXFREE0 = 9,
MT7996_RXQ_TXFREE1 = 9,
MT7996_RXQ_TXFREE2 = 7,
MT7996_RXQ_RRO_IND = 0,
MT7996_RXQ_RRO_RXDMAD_C = 0,
MT7990_RXQ_TXFREE0 = 6,
MT7990_RXQ_TXFREE1 = 7,
};
struct mt7996_twt_flow {
struct list_head list;
u64 start_tsf;
u64 tsf;
u32 duration;
u16 wcid;
__le16 mantissa;
u8 exp;
u8 table_id;
u8 id;
u8 protection:1;
u8 flowtype:1;
u8 trigger:1;
u8 sched:1;
};
DECLARE_EWMA(avg_signal, 10, 8)
struct mt7996_sta_link {
struct mt76_wcid wcid; /* must be first */
struct mt7996_sta *sta;
struct list_head rc_list;
u32 airtime_ac[8];
int ack_signal;
struct ewma_avg_signal avg_ack_signal;
unsigned long changed;
struct mt76_connac_sta_key_conf bip;
struct {
u8 flowid_mask;
struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT];
} twt;
struct rcu_head rcu_head;
};
struct mt7996_sta {
struct mt7996_sta_link deflink; /* must be first */
struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
u8 deflink_id;
u8 seclink_id;
struct mt7996_vif *vif;
};
struct mt7996_vif_link {
struct mt76_vif_link mt76; /* must be first */
struct mt7996_sta_link msta_link;
struct cfg80211_bitrate_mask bitrate_mask;
u8 mld_idx;
};
struct mt7996_vif_link_info {
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
};
struct mt7996_vif {
struct mt7996_vif_link deflink; /* must be first */
struct mt76_vif_data mt76;
struct mt7996_vif_link_info link_info[IEEE80211_MLD_MAX_NUM_LINKS];
u8 mld_group_idx;
u8 mld_remap_idx;
};
/* crash-dump */
struct mt7996_crash_data {
guid_t guid;
struct timespec64 timestamp;
u8 *memdump_buf;
size_t memdump_buf_len;
};
struct mt7996_hif {
struct list_head list;
struct device *dev;
void __iomem *regs;
int irq;
enum pci_bus_speed speed;
enum pcie_link_width width;
};
#define WED_RRO_ADDR_SIGNATURE_MASK GENMASK(31, 24)
#define WED_RRO_ADDR_COUNT_MASK GENMASK(14, 4)
#define WED_RRO_ADDR_HEAD_HIGH_MASK GENMASK(3, 0)
struct mt7996_wed_rro_addr {
__le32 head_low;
__le32 data;
};
struct mt7996_wed_rro_session_id {
struct list_head list;
u16 id;
};
struct mt7996_msdu_page {
struct list_head list;
struct mt76_queue *q;
dma_addr_t dma_addr;
void *buf;
};
/* data1 */
#define RRO_HIF_DATA1_LS_MASK BIT(30)
#define RRO_HIF_DATA1_SDL_MASK GENMASK(29, 16)
/* data4 */
#define RRO_HIF_DATA4_RX_TOKEN_ID_MASK GENMASK(15, 0)
struct mt7996_rro_hif {
__le32 data0;
__le32 data1;
__le32 data2;
__le32 data3;
__le32 data4;
__le32 data5;
};
#define MSDU_PAGE_INFO_OWNER_MASK BIT(31)
#define MSDU_PAGE_INFO_PG_HIGH_MASK GENMASK(3, 0)
struct mt7996_msdu_page_info {
struct mt7996_rro_hif rxd[MT7996_MAX_HIF_RXD_IN_PG];
__le32 pg_low;
__le32 data;
};
#define MT7996_MAX_RRO_RRS_RING 4
struct mt7996_rro_queue_regs_emi {
struct {
__le16 idx;
__le16 rsv;
} ring[MT7996_MAX_RRO_RRS_RING];
};
struct mt7996_phy {
struct mt76_phy *mt76;
struct mt7996_dev *dev;
struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
struct thermal_cooling_device *cdev;
u8 cdev_state;
u8 throttle_state;
u32 throttle_temp[2]; /* 0: critical high, 1: maximum */
u32 rxfilter;
u64 omac_mask;
u16 noise;
s16 coverage_class;
u8 slottime;
u16 beacon_rate;
u32 rx_ampdu_ts;
u32 ampdu_ref;
int txpower;
struct mt76_mib_stats mib;
struct mt76_channel_state state_ts;
u16 orig_chainmask;
u16 orig_antenna_mask;
bool has_aux_rx;
bool counter_reset;
bool rdd_tx_paused;
};
struct mt7996_dev {
union { /* must be first */
struct mt76_dev mt76;
struct mt76_phy mphy;
};
struct mt7996_phy *radio_phy[MT7996_MAX_RADIOS];
struct wiphy_radio radios[MT7996_MAX_RADIOS];
struct wiphy_radio_freq_range radio_freqs[MT7996_MAX_RADIOS];
struct mt7996_hif *hif2;
struct mt7996_reg_desc reg;
u8 q_id[MT7996_MAX_QUEUE];
u32 q_int_mask[MT7996_MAX_QUEUE];
u32 q_wfdma_mask;
u64 mld_idx_mask;
u64 mld_remap_idx_mask;
const struct mt76_bus_ops *bus_ops;
struct mt7996_phy phy;
/* monitor rx chain configured channel */
struct cfg80211_chan_def rdd2_chandef;
struct mt7996_phy *rdd2_phy;
u16 chainmask;
u8 chainshift[__MT_MAX_BAND];
u32 hif_idx;
struct work_struct init_work;
struct work_struct rc_work;
struct work_struct dump_work;
struct work_struct reset_work;
wait_queue_head_t reset_wait;
struct {
u32 state;
u32 wa_reset_count;
u32 wm_reset_count;
bool hw_full_reset:1;
bool hw_init_done:1;
bool restart:1;
} recovery;
/* protects coredump data */
struct mutex dump_mutex;
#ifdef CONFIG_DEV_COREDUMP
struct {
struct mt7996_crash_data *crash_data;
} coredump;
#endif
struct list_head sta_rc_list;
struct list_head twt_list;
u32 hw_pattern;
u8 eeprom_mode;
bool has_eht:1;
struct {
struct {
void *ptr;
dma_addr_t phy_addr;
} ba_bitmap[MT7996_RRO_BA_BITMAP_LEN];
struct {
void *ptr;
dma_addr_t phy_addr;
} addr_elem[MT7996_RRO_ADDR_ELEM_LEN];
struct {
void *ptr;
dma_addr_t phy_addr;
} session;
struct {
void *ptr;
dma_addr_t phy_addr;
} msdu_pg[MT7996_RRO_MSDU_PG_CR_CNT];
struct {
struct mt7996_rro_queue_regs_emi *ptr;
dma_addr_t phy_addr;
} emi_rings_cpu;
struct {
struct mt7996_rro_queue_regs_emi *ptr;
dma_addr_t phy_addr;
} emi_rings_dma;
struct work_struct work;
struct list_head poll_list;
spinlock_t lock;
struct list_head page_cache;
struct list_head page_map[MT7996_RRO_MSDU_PG_HASH_SIZE];
} wed_rro;
dma_addr_t npu_txd_addr[2 * MT7996_NPU_TXD_SIZE];
bool ibf;
u8 fw_debug_wm;
u8 fw_debug_wa;
u8 fw_debug_bin;
u16 fw_debug_seq;
struct dentry *debugfs_dir;
struct rchan *relay_fwlog;
struct {
u16 table_mask;
u8 n_agrt;
} twt;
spinlock_t reg_lock;
u8 wtbl_size_group;
struct {
u8 type:4;
u8 fem:4;
} var;
};
enum {
WFDMA0 = 0x0,
WFDMA1,
WFDMA_EXT,
__MT_WFDMA_MAX,
};
enum rdd_idx {
MT_RDD_IDX_BAND2, /* RDD idx for band idx 2 */
MT_RDD_IDX_BAND1, /* RDD idx for band idx 1 */
MT_RDD_IDX_BACKGROUND, /* RDD idx for background chain */
};
enum mt7996_rdd_cmd {
RDD_STOP,
RDD_START,
RDD_DET_MODE,
RDD_RADAR_EMULATE,
RDD_START_TXQ = 20,
RDD_CAC_START = 50,
RDD_CAC_END,
RDD_NORMAL_START,
RDD_DISABLE_DFS_CAL,
RDD_PULSE_DBG,
RDD_READ_PULSE,
RDD_RESUME_BF,
RDD_IRQ_OFF,
};
static inline int
mt7996_get_rdd_idx(struct mt7996_phy *phy, bool is_background)
{
if (!phy->mt76->cap.has_5ghz)
return -1;
if (is_background)
return MT_RDD_IDX_BACKGROUND;
if (phy->mt76->band_idx == MT_BAND2)
return MT_RDD_IDX_BAND2;
return MT_RDD_IDX_BAND1;
}
static inline struct mt7996_dev *
mt7996_hw_dev(struct ieee80211_hw *hw)
{
struct mt76_phy *phy = hw->priv;
return container_of(phy->dev, struct mt7996_dev, mt76);
}
static inline struct mt7996_phy *
__mt7996_phy(struct mt7996_dev *dev, enum mt76_band_id band)
{
struct mt76_phy *phy = dev->mt76.phys[band];
if (!phy)
return NULL;
return phy->priv;
}
static inline struct mt7996_phy *
mt7996_phy2(struct mt7996_dev *dev)
{
return __mt7996_phy(dev, MT_BAND1);
}
static inline struct mt7996_phy *
mt7996_phy3(struct mt7996_dev *dev)
{
return __mt7996_phy(dev, MT_BAND2);
}
static inline bool
mt7996_band_valid(struct mt7996_dev *dev, u8 band)
{
if (!is_mt7996(&dev->mt76))
return band <= MT_BAND1;
return band <= MT_BAND2;
}
static inline struct mt7996_phy *
mt7996_band_phy(struct mt7996_dev *dev, enum nl80211_band band)
{
struct mt76_phy *mphy;
mphy = dev->mt76.band_phys[band];
if (!mphy)
return NULL;
return mphy->priv;
}
static inline struct mt7996_vif_link *
mt7996_vif_link(struct mt7996_dev *dev, struct ieee80211_vif *vif, int link_id)
{
return (struct mt7996_vif_link *)mt76_vif_link(&dev->mt76, vif, link_id);
}
static inline struct mt7996_phy *
mt7996_vif_link_phy(struct mt7996_vif_link *link)
{
struct mt76_phy *mphy = mt76_vif_link_phy(&link->mt76);
if (!mphy)
return NULL;
return mphy->priv;
}
static inline struct mt7996_vif_link *
mt7996_vif_conf_link(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
return (struct mt7996_vif_link *)mt76_vif_conf_link(&dev->mt76, vif,
link_conf);
}
static inline struct mt7996_sta_link *
mt7996_sta_link(struct mt7996_sta *msta, u8 link_id)
{
if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
return NULL;
return rcu_dereference(msta->link[link_id]);
}
static inline struct mt7996_sta_link *
mt7996_sta_link_protected(struct mt7996_dev *dev, struct mt7996_sta *msta,
u8 link_id)
{
if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
return NULL;
return mt76_dereference(msta->link[link_id], &dev->mt76);
}
#define mt7996_for_each_phy(dev, phy) \
for (int __i = 0; __i < ARRAY_SIZE((dev)->radio_phy); __i++) \
if (((phy) = (dev)->radio_phy[__i]) != NULL)
extern const struct ieee80211_ops mt7996_ops;
extern struct pci_driver mt7996_pci_driver;
extern struct pci_driver mt7996_hif_driver;
struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
void __iomem *mem_base, u32 device_id);
void mt7996_rro_hw_init(struct mt7996_dev *dev);
void mt7996_wfsys_reset(struct mt7996_dev *dev);
irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link);
int mt7996_register_device(struct mt7996_dev *dev);
void mt7996_unregister_device(struct mt7996_dev *dev);
int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct mt76_vif_link *mlink);
void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct mt76_vif_link *mlink);
int mt7996_eeprom_init(struct mt7996_dev *dev);
int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
struct ieee80211_channel *chan);
s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev);
int mt7996_dma_init(struct mt7996_dev *dev);
void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
void mt7996_dma_prefetch(struct mt7996_dev *dev);
void mt7996_dma_cleanup(struct mt7996_dev *dev);
void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset);
int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx,
int n_desc, int ring_base, struct mtk_wed_device *wed);
void mt7996_init_txpower(struct mt7996_phy *phy);
int mt7996_txbf_init(struct mt7996_dev *dev);
void mt7996_reset(struct mt7996_dev *dev);
int mt7996_run(struct mt7996_phy *phy);
int mt7996_mcu_init(struct mt7996_dev *dev);
int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
struct mt7996_vif_link *link,
struct mt7996_twt_flow *flow,
int cmd);
int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct mt76_vif_link *mlink, bool enable);
int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct mt76_vif_link *mlink,
struct mt7996_sta_link *msta_link, int enable);
int mt7996_mcu_update_bss_rfch(struct mt7996_phy *phy,
struct mt7996_vif_link *link);
int mt7996_mcu_add_sta(struct mt7996_dev *dev,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
int conn_state, bool newly);
int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link);
void mt7996_mcu_update_sta_rec_bw(void *data, struct ieee80211_sta *sta);
int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
struct ieee80211_ampdu_params *params,
struct ieee80211_vif *vif, bool enable);
int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
struct ieee80211_ampdu_params *params,
struct ieee80211_vif *vif, bool enable);
int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
struct mt76_vif_link *mlink,
struct cfg80211_he_bss_color *he_bss_color);
int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf, bool enabled);
int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
struct ieee80211_bss_conf *link_conf,
struct mt7996_vif_link *link, u32 changed);
int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
struct mt7996_vif_link *link,
struct ieee80211_he_obss_pd *he_obss_pd);
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta,
struct ieee80211_vif *vif, u8 link_id,
bool changed);
int mt7996_set_channel(struct mt76_phy *mphy);
int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
void *data, u16 version);
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
void *data, u8 link_id, u32 field);
int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len,
enum mt7996_eeprom_mode mode);
int mt7996_mcu_get_efuse_free_block(struct mt7996_dev *dev, u8 *block_num);
int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap);
int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band);
int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action);
int mt7996_mcu_set_fcc5_lpn(struct mt7996_dev *dev, int val);
int mt7996_mcu_set_pulse_th(struct mt7996_dev *dev,
const struct mt7996_dfs_pulse *pulse);
int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
const struct mt7996_dfs_pattern *pattern);
int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *link,
u8 ht_mode, bool use_cts_prot);
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
int mt7996_mcu_rdd_resume_tx(struct mt7996_phy *phy);
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val);
int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
struct cfg80211_chan_def *chandef);
int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
u16 rate_idx, bool beacon);
int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val);
int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
void mt7996_mcu_exit(struct mt7996_dev *dev);
int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
int mt7996_mcu_set_sniffer_mode(struct mt7996_phy *phy, bool enabled);
int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev);
int mt7996_mcu_mld_reconf_stop_link(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
u16 removed_links);
int mt7996_mcu_mld_link_oper(struct mt7996_dev *dev,
struct ieee80211_bss_conf *link_conf,
struct mt7996_vif_link *link, bool add);
static inline bool mt7996_has_hwrro(struct mt7996_dev *dev)
{
return dev->mt76.hwrro_mode != MT76_HWRRO_OFF;
}
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
{
return min(MT7996_MAX_INTERFACES * (1 + mt7996_band_valid(dev, MT_BAND1) +
mt7996_band_valid(dev, MT_BAND2)),
MT7996_WTBL_BMC_SIZE);
}
static inline u16 mt7996_wtbl_size(struct mt7996_dev *dev)
{
return (dev->wtbl_size_group << 8) + MT7996_WTBL_BMC_SIZE;
}
void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
u32 clear, u32 set);
static inline void mt7996_irq_enable(struct mt7996_dev *dev, u32 mask)
{
if (dev->hif2)
mt7996_dual_hif_set_irq_mask(dev, false, 0, mask);
else
mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
tasklet_schedule(&dev->mt76.irq_tasklet);
}
static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
{
if (dev->hif2)
mt7996_dual_hif_set_irq_mask(dev, true, mask, 0);
else
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
}
void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
size_t len);
static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
{
int max_nss = hweight16(phy->orig_antenna_mask);
int cur_nss = hweight8(phy->mt76->antenna_mask);
u16 tx_chainmask = phy->mt76->chainmask;
if (cur_nss != max_nss)
return tx_chainmask;
return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
}
static inline bool mt7996_has_wa(struct mt7996_dev *dev)
{
return !is_mt7990(&dev->mt76);
}
static inline bool mt7996_has_ext_eeprom(struct mt7996_dev *dev)
{
return !is_mt7996(&dev->mt76);
}
void mt7996_mac_init(struct mt7996_dev *dev);
u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
void mt7996_mac_reset_counters(struct mt7996_phy *phy);
void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, int pid,
enum mt76_txq_id qid, u32 changed,
unsigned int link_id);
void mt7996_mac_update_beacons(struct mt7996_phy *phy);
void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
void mt7996_mac_work(struct work_struct *work);
void mt7996_mac_reset_work(struct work_struct *work);
void mt7996_mac_dump_work(struct work_struct *work);
void mt7996_mac_sta_rc_work(struct work_struct *work);
void mt7996_mac_update_stats(struct mt7996_phy *phy);
void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
u8 flowid);
void mt7996_mac_sta_remove_link(struct mt7996_dev *dev,
struct ieee80211_sta *sta,
unsigned int link_id, bool flush);
void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct ieee80211_twt_setup *twt);
int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt7996_tx_token_put(struct mt7996_dev *dev);
void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
void mt7996_rro_msdu_page_map_free(struct mt7996_dev *dev);
int mt7996_rro_msdu_page_add(struct mt76_dev *mdev, struct mt76_queue *q,
dma_addr_t dma_addr, void *data);
void mt7996_rro_rx_process(struct mt76_dev *mdev, void *data);
bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
void mt7996_stats_work(struct work_struct *work);
int mt76_dfs_start_rdd(struct mt7996_dev *dev, bool force);
int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy);
void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy);
void mt7996_set_stream_vht_txbf_caps(struct mt7996_phy *phy);
void mt7996_update_channel(struct mt76_phy *mphy);
int mt7996_init_debugfs(struct mt7996_dev *dev);
void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len);
bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len);
int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link,
struct ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd);
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
struct ieee80211_key_conf *key);
int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link);
int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
int mt7996_mcu_set_emlsr_mode(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_eml_params *eml_params);
#ifdef CONFIG_MAC80211_DEBUGFS
void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir);
void mt7996_link_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta,
struct dentry *dir);
#endif
int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
bool hif2, int *irq);
u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
#ifdef CONFIG_MTK_DEBUG
int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
#endif
int mt7996_dma_rro_init(struct mt7996_dev *dev);
void mt7996_dma_rro_start(struct mt7996_dev *dev);
#ifdef CONFIG_MT7996_NPU
int __mt7996_npu_hw_init(struct mt7996_dev *dev);
int mt7996_npu_hw_init(struct mt7996_dev *dev);
int mt7996_npu_hw_stop(struct mt7996_dev *dev);
int mt7996_npu_rx_queues_init(struct mt7996_dev *dev);
#else
static inline int __mt7996_npu_hw_init(struct mt7996_dev *dev)
{
return 0;
}
static inline int mt7996_npu_hw_init(struct mt7996_dev *dev)
{
return 0;
}
static inline int mt7996_npu_hw_stop(struct mt7996_dev *dev)
{
return 0;
}
static inline int mt7996_npu_rx_queues_init(struct mt7996_dev *dev)
{
return 0;
}
#endif /* CONFIG_MT7996_NPU */
#endif
@@ -0,0 +1,631 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2025 AIROHA Inc
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
*/
#include <linux/kernel.h>
#include <linux/soc/airoha/airoha_offload.h>
#include "mt7996.h"
static int mt7992_npu_txrx_offload_init(struct mt7996_dev *dev,
struct airoha_npu *npu)
{
u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
u32 dma_addr;
int i, err;
for (i = MT_BAND0; i < MT_BAND2; i++) {
err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_DESC,
MT7996_RX_RING_SIZE, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rx desc size\n");
return err;
}
dma_addr = phy_addr;
if (i)
dma_addr += MT_TXQ_RING_BASE(0) + 0x150 + hif1_ofs;
else
dma_addr += MT_TXQ_RING_BASE(0) + 0x120;
err = mt76_npu_send_msg(npu, i,
WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
dma_addr, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan tx desc addr\n");
return err;
}
}
err = mt76_npu_send_msg(npu, 9, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
phy_addr + MT_RXQ_RRO_AP_RING_BASE,
GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rxdmad_c addr\n");
return err;
}
err = mt76_npu_send_msg(npu, 9, WLAN_FUNC_SET_WAIT_DESC,
MT7996_RX_RING_SIZE, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rxdmad_c desc size\n");
return err;
}
err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan tx desc addr\n");
return err;
}
return 0;
}
static int mt7996_npu_txrx_offload_init(struct mt7996_dev *dev,
struct airoha_npu *npu)
{
u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
u32 dma_addr;
int err;
/* npu rx rro ring0 */
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_DESC,
MT7996_RX_RING_SIZE, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rx desc size\n");
return err;
}
/* npu rx rro ring1 */
err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_DESC,
MT7996_NPU_RX_RING_SIZE, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rx desc size\n");
return err;
}
/* msdu pg 2GHz */
dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0) + 0xa0;
err = mt76_npu_send_msg(npu, 5, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
dma_addr, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan PCIe desc addr\n");
return err;
}
err = mt76_npu_send_msg(npu, 5, WLAN_FUNC_SET_WAIT_DESC,
MT7996_NPU_RX_RING_SIZE / 4, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rx desc size\n");
return err;
}
/* msdu pg 5GHz */
dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1) + 0xb0;
err = mt76_npu_send_msg(npu, 6, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
dma_addr, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan PCIe desc addr\n");
return err;
}
err = mt76_npu_send_msg(npu, 6, WLAN_FUNC_SET_WAIT_DESC,
MT7996_NPU_RX_RING_SIZE / 2, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rx desc size\n");
return err;
}
/* msdu pg 6GHz */
dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2) + 0xc0;
err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
dma_addr, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan PCIe desc addr\n");
return err;
}
err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_DESC,
MT7996_NPU_RX_RING_SIZE, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rx desc size\n");
return err;
}
/* ind cmd ring */
err = mt76_npu_send_msg(npu, 8, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
phy_addr + MT_RXQ_RRO_IND_RING_BASE,
GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan PCIe desc addr\n");
return err;
}
err = mt76_npu_send_msg(npu, 8, WLAN_FUNC_SET_WAIT_DESC,
MT7996_RX_RING_SIZE, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rx desc size\n");
return err;
}
err = mt76_npu_send_msg(npu, 3, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan tx desc addr\n");
return err;
}
/* npu tx */
dma_addr = phy_addr + MT_TXQ_RING_BASE(1) + 0x120;
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
dma_addr, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan tx desc addr\n");
return err;
}
dma_addr = phy_addr + MT_TXQ_RING_BASE(0) + 0x150 + hif1_ofs;
err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
dma_addr, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan tx desc addr\n");
return err;
}
return 0;
}
static int mt7996_npu_offload_init(struct mt7996_dev *dev,
struct airoha_npu *npu)
{
u32 val;
int err;
err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_NPU_VERSION,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev, "failed getting NPU fw version\n");
return err;
}
dev_info(dev->mt76.dev, "NPU version: %0d.%d\n",
(val >> 16) & 0xffff, val & 0xffff);
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE,
dev->mt76.mmio.npu_type, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan PCIe port type\n");
return err;
}
if (is_mt7996(&dev->mt76))
err = mt7996_npu_txrx_offload_init(dev, npu);
else
err = mt7992_npu_txrx_offload_init(dev, npu);
if (err)
return err;
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE,
MT7996_HW_TOKEN_SIZE, GFP_KERNEL);
if (err)
return err;
dev->mt76.token_start = MT7996_HW_TOKEN_SIZE;
return 0;
}
static int mt7992_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
{
u32 val;
int err;
err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retrieving NPU wlan rx ring0 addr\n");
return err;
}
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);
err = mt76_npu_get_msg(npu, 1, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retrieving NPU wlan rx ring1 addr\n");
return err;
}
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND1].regs->desc_base);
err = mt76_npu_get_msg(npu, 9, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retrieving NPU wlan rxdmad_c ring addr\n");
return err;
}
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_RXDMAD_C].regs->desc_base);
return 0;
}
static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
{
u32 val;
int err;
err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retriving NPU wlan rx ring0 addr\n");
return err;
}
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);
err = mt76_npu_get_msg(npu, 2, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retriving NPU wlan rx ring2 addr\n");
return err;
}
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2].regs->desc_base);
/* msdu pg ring */
err = mt76_npu_get_msg(npu, 10, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retriving NPU wlan msdu pg ring addr\n");
return err;
}
writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].regs->desc_base);
err = mt76_npu_get_msg(npu, 11, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retriving NPU wlan msdu pg ring addr\n");
return err;
}
writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].regs->desc_base);
err = mt76_npu_get_msg(npu, 12, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retriving NPU wlan msdu pg ring addr\n");
return err;
}
writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].regs->desc_base);
/* ind_cmd ring */
err = mt76_npu_get_msg(npu, 8, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retriving NPU wlan ind_cmd ring addr\n");
return err;
}
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_IND].regs->desc_base);
return 0;
}
static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
{
const enum mt76_band_id band_list[] = {
MT_BAND0,
is_mt7996(&dev->mt76) ? MT_BAND2 : MT_BAND1,
};
int i, index = 0;
BUILD_BUG_ON(ARRAY_SIZE(band_list) * 3 !=
ARRAY_SIZE(dev->npu_txd_addr));
for (i = 0; i < ARRAY_SIZE(band_list); i++) {
int err, band = band_list[i], phy_id;
u32 val;
err = mt76_npu_get_msg(npu, band + 5,
WLAN_FUNC_GET_WAIT_RXDESC_BASE,
&val, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed retrieving NPU wlan tx ring addr\n");
return err;
}
phy_id = is_mt7996(&dev->mt76) ? band == MT_BAND0 ? 1 : 0
: band;
writel(val, &dev->mt76.phys[phy_id]->q_tx[0]->regs->desc_base);
err = mt76_npu_send_msg(npu, band,
WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
dev->npu_txd_addr[index++], GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan queue buf addr\n");
return err;
}
err = mt76_npu_send_msg(npu, band + 5,
WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
dev->npu_txd_addr[index++],
GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan tx buf addr\n");
return err;
}
err = mt76_npu_send_msg(npu, band + 10,
WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
dev->npu_txd_addr[index++],
GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan tx buf base\n");
return err;
}
}
return 0;
}
static int mt7996_npu_rx_event_init(struct mt7996_dev *dev,
struct airoha_npu *npu)
{
int qid = is_mt7996(&dev->mt76) ? MT_RXQ_TXFREE_BAND0 : MT_RXQ_MAIN_WA;
phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
struct mt76_queue *q = &dev->mt76.q_rx[qid];
int err;
err = mt76_npu_send_msg(npu, 0,
WLAN_FUNC_SET_WAIT_RX_RING_FOR_TXDONE_HW_BASE,
q->desc_dma, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan tx-done ring\n");
return err;
}
err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_DESC,
MT7996_RX_MCU_RING_SIZE, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan descriptors\n");
return err;
}
phy_addr += MT_RXQ_RING_BASE(qid);
phy_addr += is_mt7996(&dev->mt76) ? 0x90 : 0x20;
err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
phy_addr, GFP_KERNEL);
if (err)
dev_warn(dev->mt76.dev,
"failed setting NPU wlan rx pcie address\n");
return err;
}
static int mt7996_npu_set_pcie_addr(struct mt7996_dev *dev,
struct airoha_npu *npu)
{
u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
dma_addr_t dma_addr = dev->mt76.mmio.phy_addr;
int err;
dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0) + 0x80;
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
dma_addr, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan PCIe desc addr\n");
return err;
}
dma_addr = dev->mt76.mmio.phy_addr + hif1_ofs;
if (is_mt7996(&dev->mt76)) {
dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + 0x60;
err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
dma_addr, GFP_KERNEL);
} else {
dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + 0x90;
err = mt76_npu_send_msg(npu, 1, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
dma_addr, GFP_KERNEL);
}
if (err)
dev_warn(dev->mt76.dev,
"failed setting NPU wlan PCIe desc addr\n");
return err;
}
static int mt7996_npu_tx_done_init(struct mt7996_dev *dev,
struct airoha_npu *npu)
{
int err;
/* rro ring cpu idx */
err = mt76_npu_send_msg(npu, 15, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
0, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev,
"failed setting NPU wlan PCIe desc addr\n");
return err;
}
err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
0, GFP_KERNEL);
if (err) {
dev_warn(dev->mt76.dev, "failed setting NPU wlan txrx addr2\n");
return err;
}
err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
0, GFP_KERNEL);
if (err)
dev_warn(dev->mt76.dev, "failed setting NPU wlan txrx addr7\n");
return err;
}
int mt7996_npu_rx_queues_init(struct mt7996_dev *dev)
{
int err;
if (!mt76_npu_device_active(&dev->mt76))
return 0;
err = mt76_npu_rx_queue_init(&dev->mt76,
&dev->mt76.q_rx[MT_RXQ_NPU0]);
if (err)
return err;
return mt76_npu_rx_queue_init(&dev->mt76,
&dev->mt76.q_rx[MT_RXQ_NPU1]);
}
int __mt7996_npu_hw_init(struct mt7996_dev *dev)
{
struct airoha_npu *npu;
int i, err;
npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
if (!npu)
return 0;
err = mt7996_npu_offload_init(dev, npu);
if (err)
return err;
if (is_mt7996(&dev->mt76))
err = mt7996_npu_rxd_init(dev, npu);
else
err = mt7992_npu_rxd_init(dev, npu);
if (err)
return err;
err = mt7996_npu_txd_init(dev, npu);
if (err)
return err;
err = mt7996_npu_rx_event_init(dev, npu);
if (err)
return err;
err = mt7996_npu_set_pcie_addr(dev, npu);
if (err)
return err;
err = mt7996_npu_tx_done_init(dev, npu);
if (err)
return err;
for (i = MT_RXQ_NPU0; i <= MT_RXQ_NPU1; i++)
airoha_npu_wlan_enable_irq(npu, i - MT_RXQ_NPU0);
return 0;
}
int mt7996_npu_hw_init(struct mt7996_dev *dev)
{
int i, err;
BUILD_BUG_ON(ARRAY_SIZE(dev->npu_txd_addr) % 3);
for (i = 0; i < ARRAY_SIZE(dev->npu_txd_addr); i += 3) {
int band = i && is_mt7996(&dev->mt76) ? MT_BAND2 : MT_BAND0;
u32 size = is_mt7996(&dev->mt76) ? band == MT_BAND2
? MT7996_NPU_TX_RING_SIZE
: MT7996_NPU_RX_RING_SIZE / 2
: MT7996_TX_RING_SIZE;
if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * size,
&dev->npu_txd_addr[i], GFP_KERNEL))
return -ENOMEM;
if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * size,
&dev->npu_txd_addr[i + 1],
GFP_KERNEL))
return -ENOMEM;
if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * 1024,
&dev->npu_txd_addr[i + 2],
GFP_KERNEL))
return -ENOMEM;
}
mutex_lock(&dev->mt76.mutex);
err = __mt7996_npu_hw_init(dev);
mutex_unlock(&dev->mt76.mutex);
return err;
}
int mt7996_npu_hw_stop(struct mt7996_dev *dev)
{
struct airoha_npu *npu;
int i, err = 0;
u32 info;
mutex_lock(&dev->mt76.mutex);
npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
if (!npu)
goto unlock;
err = mt76_npu_send_msg(npu, 4, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
0, GFP_KERNEL);
if (err)
goto unlock;
for (i = 0; i < 10; i++) {
err = mt76_npu_get_msg(npu, 3, WLAN_FUNC_GET_WAIT_NPU_INFO,
&info, GFP_KERNEL);
if (!err && !info)
break;
err = -ETIMEDOUT;
usleep_range(10000, 15000);
}
if (!err)
err = mt76_npu_send_msg(npu, 6,
WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
0, GFP_KERNEL);
else
dev_err(dev->mt76.dev, "npu stop failed\n");
unlock:
mutex_unlock(&dev->mt76.mutex);
return err;
}
@@ -0,0 +1,269 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (C) 2022 MediaTek Inc.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "mt7996.h"
#include "mac.h"
#include "../trace.h"
static LIST_HEAD(hif_list);
static DEFINE_SPINLOCK(hif_lock);
static u32 hif_idx;
static const struct pci_device_id mt7996_pci_device_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID) },
{ },
};
static const struct pci_device_id mt7996_hif_device_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID_2) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID_2) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID_2) },
{ },
};
static struct mt7996_hif *mt7996_pci_get_hif2(u32 idx)
{
struct mt7996_hif *hif;
u32 val;
spin_lock_bh(&hif_lock);
list_for_each_entry(hif, &hif_list, list) {
val = readl(hif->regs + MT_PCIE_RECOG_ID);
val &= MT_PCIE_RECOG_ID_MASK;
if (val != idx)
continue;
get_device(hif->dev);
goto out;
}
hif = NULL;
out:
spin_unlock_bh(&hif_lock);
return hif;
}
static void mt7996_put_hif2(struct mt7996_hif *hif)
{
if (!hif)
return;
put_device(hif->dev);
}
static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev)
{
hif_idx++;
if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID_2, NULL) &&
!pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID_2, NULL) &&
!pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID_2, NULL))
return NULL;
writel(hif_idx | MT_PCIE_RECOG_ID_SEM,
pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID);
return mt7996_pci_get_hif2(hif_idx);
}
static int mt7996_pci_hif2_probe(struct pci_dev *pdev)
{
struct mt7996_hif *hif;
hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL);
if (!hif)
return -ENOMEM;
hif->dev = &pdev->dev;
hif->regs = pcim_iomap_table(pdev)[0];
hif->irq = pdev->irq;
pcie_bandwidth_available(pdev, NULL, &hif->speed, &hif->width);
spin_lock_bh(&hif_lock);
list_add(&hif->list, &hif_list);
spin_unlock_bh(&hif_lock);
pci_set_drvdata(pdev, hif);
return 0;
}
static int mt7996_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct pci_dev *hif2_dev;
struct mt7996_hif *hif2;
struct mt7996_dev *dev;
int irq, hif2_irq, ret;
struct mt76_dev *mdev;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
if (ret)
return ret;
pci_set_master(pdev);
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
if (ret)
return ret;
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
mt76_pci_disable_aspm(pdev);
if (id->device == MT7996_DEVICE_ID_2 ||
id->device == MT7992_DEVICE_ID_2 ||
id->device == MT7990_DEVICE_ID_2)
return mt7996_pci_hif2_probe(pdev);
dev = mt7996_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
id->device);
if (IS_ERR(dev))
return PTR_ERR(dev);
mdev = &dev->mt76;
mt7996_wfsys_reset(dev);
hif2 = mt7996_pci_init_hif2(pdev);
dev->hif2 = hif2;
mt76_npu_init(mdev, pci_resource_start(pdev, 0),
pci_domain_nr(pdev->bus) ? 3 : 2);
ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);
if (ret < 0)
goto free_wed_or_irq_vector;
if (!ret) {
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
if (ret < 0)
goto free_device;
irq = pdev->irq;
}
ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto free_wed_or_irq_vector;
mt76_wr(dev, MT_INT_MASK_CSR, 0);
/* master switch of PCIe interrupt enable */
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
if (hif2) {
hif2_dev = container_of(hif2->dev, struct pci_dev, dev);
ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &hif2_irq);
if (ret < 0)
goto free_hif2_wed_irq_vector;
if (!ret) {
ret = pci_alloc_irq_vectors(hif2_dev, 1, 1,
PCI_IRQ_ALL_TYPES);
if (ret < 0)
goto free_hif2;
dev->hif2->irq = hif2_dev->irq;
hif2_irq = dev->hif2->irq;
}
ret = devm_request_irq(mdev->dev, hif2_irq, mt7996_irq_handler,
IRQF_SHARED, KBUILD_MODNAME "-hif",
dev);
if (ret)
goto free_hif2_wed_irq_vector;
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
/* master switch of PCIe tnterrupt enable */
mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
}
ret = mt7996_register_device(dev);
if (ret)
goto free_hif2_irq;
return 0;
free_hif2_irq:
if (dev->hif2)
devm_free_irq(mdev->dev, hif2_irq, dev);
free_hif2_wed_irq_vector:
if (dev->hif2) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
mtk_wed_device_detach(&dev->mt76.mmio.wed_hif2);
else
pci_free_irq_vectors(hif2_dev);
}
free_hif2:
if (dev->hif2)
put_device(dev->hif2->dev);
devm_free_irq(mdev->dev, irq, dev);
free_wed_or_irq_vector:
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
mtk_wed_device_detach(&dev->mt76.mmio.wed);
else
pci_free_irq_vectors(pdev);
free_device:
mt76_free_device(&dev->mt76);
return ret;
}
static void mt7996_hif_remove(struct pci_dev *pdev)
{
struct mt7996_hif *hif = pci_get_drvdata(pdev);
list_del(&hif->list);
}
static void mt7996_pci_remove(struct pci_dev *pdev)
{
struct mt76_dev *mdev;
struct mt7996_dev *dev;
mdev = pci_get_drvdata(pdev);
dev = container_of(mdev, struct mt7996_dev, mt76);
mt7996_put_hif2(dev->hif2);
mt7996_unregister_device(dev);
}
struct pci_driver mt7996_hif_driver = {
.name = KBUILD_MODNAME "_hif",
.id_table = mt7996_hif_device_table,
.probe = mt7996_pci_probe,
.remove = mt7996_hif_remove,
};
struct pci_driver mt7996_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = mt7996_pci_device_table,
.probe = mt7996_pci_probe,
.remove = mt7996_pci_remove,
};
MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table);
MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table);
MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
MODULE_FIRMWARE(MT7996_ROM_PATCH);
MODULE_FIRMWARE(MT7992_FIRMWARE_WA);
MODULE_FIRMWARE(MT7992_FIRMWARE_WM);
MODULE_FIRMWARE(MT7992_FIRMWARE_DSP);
MODULE_FIRMWARE(MT7992_ROM_PATCH);
MODULE_FIRMWARE(MT7990_FIRMWARE_WM);
MODULE_FIRMWARE(MT7990_ROM_PATCH);
@@ -0,0 +1,802 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (C) 2022 MediaTek Inc.
*/
#ifndef __MT7996_REGS_H
#define __MT7996_REGS_H
struct __map {
u32 phys;
u32 mapped;
u32 size;
};
struct __base {
u32 band_base[__MT_MAX_BAND];
};
/* used to differentiate between generations */
struct mt7996_reg_desc {
const struct __base *base;
const u32 *offs_rev;
const struct __map *map;
u32 map_size;
};
enum base_rev {
WF_AGG_BASE,
WF_ARB_BASE,
WF_TMAC_BASE,
WF_RMAC_BASE,
WF_DMA_BASE,
WF_WTBLOFF_BASE,
WF_ETBF_BASE,
WF_LPON_BASE,
WF_MIB_BASE,
WF_RATE_BASE,
__MT_REG_BASE_MAX,
};
#define __BASE(_id, _band) (dev->reg.base[(_id)].band_base[(_band)])
enum offs_rev {
MIB_RVSR0,
MIB_RVSR1,
MIB_BTSCR5,
MIB_BTSCR6,
MIB_RSCR1,
MIB_RSCR27,
MIB_RSCR28,
MIB_RSCR29,
MIB_RSCR30,
MIB_RSCR31,
MIB_RSCR33,
MIB_RSCR35,
MIB_RSCR36,
MIB_BSCR0,
MIB_BSCR1,
MIB_BSCR2,
MIB_BSCR3,
MIB_BSCR4,
MIB_BSCR5,
MIB_BSCR6,
MIB_BSCR7,
MIB_BSCR17,
MIB_TRDR1,
HIF_REMAP_L1,
HIF_REMAP_BASE_L1,
HIF_REMAP_L2,
HIF_REMAP_BASE_L2,
CBTOP1_PHY_END,
INFRA_MCU_END,
WTBLON_WDUCR,
WTBL_UPDATE,
WTBL_ITCR,
WTBL_ITCR0,
WTBL_ITCR1,
__MT_OFFS_MAX,
};
#define __OFFS(id) (dev->reg.offs_rev[(id)])
/* RRO TOP */
#define MT_RRO_TOP_BASE 0xA000
#define MT_RRO_TOP(ofs) (MT_RRO_TOP_BASE + (ofs))
#define MT_RRO_BA_BITMAP_BASE0 MT_RRO_TOP(0x8)
#define MT_RRO_BA_BITMAP_BASE1 MT_RRO_TOP(0xC)
#define WF_RRO_AXI_MST_CFG MT_RRO_TOP(0xB8)
#define WF_RRO_AXI_MST_CFG_DIDX_OK BIT(12)
#define MT_RRO_ADDR_ARRAY_BASE0 MT_RRO_TOP(0x30)
#define MT_RRO_ADDR_ARRAY_BASE1 MT_RRO_TOP(0x34)
#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE BIT(31)
#define MT_RRO_IND_CMD_SIGNATURE_BASE0 MT_RRO_TOP(0x38)
#define MT_RRO_IND_CMD_SIGNATURE_BASE1 MT_RRO_TOP(0x3C)
#define MT_RRO_IND_CMD_0_CTRL0 MT_RRO_TOP(0x40)
#define MT_RRO_IND_CMD_SIGNATURE_BASE1_EN BIT(31)
#define MT_RRO_PARTICULAR_CFG0 MT_RRO_TOP(0x5C)
#define MT_RRO_PARTICULAR_CFG1 MT_RRO_TOP(0x60)
#define MT_RRO_PARTICULAR_CONFG_EN BIT(31)
#define MT_RRO_PARTICULAR_SID GENMASK(30, 16)
#define MT_RRO_BA_BITMAP_BASE_EXT0 MT_RRO_TOP(0x70)
#define MT_RRO_BA_BITMAP_BASE_EXT1 MT_RRO_TOP(0x74)
#define MT_RRO_HOST_INT_ENA MT_RRO_TOP(0x204)
#define MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA BIT(0)
#define MT_RRO_ADDR_ELEM_SEG_ADDR0 MT_RRO_TOP(0x400)
#define MT_RRO_3_0_EMU_CONF MT_RRO_TOP(0x600)
#define MT_RRO_3_0_EMU_CONF_EN_MASK BIT(11)
#define MT_RRO_3_1_GLOBAL_CONFIG MT_RRO_TOP(0x604)
#define MT_RRO_3_1_GLOBAL_CONFIG_RXDMAD_SEL BIT(6)
#define MT_RRO_3_1_GLOBAL_CONFIG_RX_CIDX_RD_EN BIT(3)
#define MT_RRO_3_1_GLOBAL_CONFIG_RX_DIDX_WR_EN BIT(2)
#define MT_RRO_3_1_GLOBAL_CONFIG_INTERLEAVE_EN BIT(0)
#define MT_RRO_MSDU_PG_SEG_ADDR0 MT_RRO_TOP(0x620)
#define MT_RRO_RX_RING_AP_CIDX_ADDR MT_RRO_TOP(0x6f0)
#define MT_RRO_RX_RING_AP_DIDX_ADDR MT_RRO_TOP(0x6f4)
#define MT_RRO_ACK_SN_CTRL MT_RRO_TOP(0x50)
#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
#define MT_RRO_DBG_RD_CTRL MT_RRO_TOP(0xe0)
#define MT_RRO_DBG_RD_ADDR GENMASK(15, 0)
#define MT_RRO_DBG_RD_EXEC BIT(31)
#define MT_RRO_DBG_RDAT_DW(_n) MT_RRO_TOP(0xf0 + (_n) * 0x4)
#define MT_MCU_INT_EVENT 0x2108
#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
#define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
#define MT_MCU_INT_EVENT_RESET_DONE BIT(3)
/* PLE */
#define MT_PLE_BASE 0x820c0000
#define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
#define MT_FL_Q_EMPTY MT_PLE(0x360)
#define MT_FL_Q0_CTRL MT_PLE(0x3e0)
#define MT_FL_Q2_CTRL MT_PLE(0x3e8)
#define MT_FL_Q3_CTRL MT_PLE(0x3ec)
#define MT_PLE_FREEPG_CNT MT_PLE(0x380)
#define MT_PLE_FREEPG_HEAD_TAIL MT_PLE(0x384)
#define MT_PLE_PG_HIF_GROUP MT_PLE(0x00c)
#define MT_PLE_HIF_PG_INFO MT_PLE(0x388)
#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x600 + 0x80 * (ac) + ((n) << 2))
#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
/* WF MDP TOP */
#define MT_MDP_BASE 0x820cc000
#define MT_MDP(ofs) (MT_MDP_BASE + (ofs))
#define MT_MDP_DCR0 MT_MDP(0x800)
#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19)
#define MT_MDP_DCR2 MT_MDP(0x8e8)
#define MT_MDP_DCR2_RX_TRANS_SHORT BIT(2)
/* TMAC: band 0(0x820e4000), band 1(0x820f4000), band 2(0x830e4000) */
#define MT_WF_TMAC_BASE(_band) __BASE(WF_TMAC_BASE, (_band))
#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))
#define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0)
#define MT_TMAC_TCR0_TX_BLINK GENMASK(7, 6)
#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x0c8)
#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x0cc)
#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0)
#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16)
#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x014)
#define MT_IFS_EIFS_OFDM GENMASK(8, 0)
#define MT_IFS_RIFS GENMASK(14, 10)
#define MT_IFS_SIFS GENMASK(22, 16)
#define MT_IFS_SLOT GENMASK(30, 24)
#define MT_TMAC_ICR1(_band) MT_WF_TMAC(_band, 0x018)
#define MT_IFS_EIFS_CCK GENMASK(8, 0)
/* WF DMA TOP: band 0(0x820e7000), band 1(0x820f7000), band 2(0x830e7000) */
#define MT_WF_DMA_BASE(_band) __BASE(WF_DMA_BASE, (_band))
#define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs))
#define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000)
#define MT_DMA_DCR0_RXD_G5_EN BIT(23)
#define MT_DMA_TCRF1(_band) MT_WF_DMA(_band, 0x054)
#define MT_DMA_TCRF1_QIDX GENMASK(15, 13)
/* WTBLOFF TOP: band 0(0x820e9000), band 1(0x820f9000), band 2(0x830e9000) */
#define MT_WTBLOFF_BASE(_band) __BASE(WF_WTBLOFF_BASE, (_band))
#define MT_WTBLOFF(_band, ofs) (MT_WTBLOFF_BASE(_band) + (ofs))
#define MT_WTBLOFF_RSCR(_band) MT_WTBLOFF(_band, 0x008)
#define MT_WTBLOFF_RSCR_RCPI_MODE GENMASK(31, 30)
#define MT_WTBLOFF_RSCR_RCPI_PARAM GENMASK(25, 24)
#define MT_WTBLOFF_ACR(_band) MT_WTBLOFF(_band, 0x010)
#define MT_WTBLOFF_ADM_BACKOFFTIME BIT(29)
/* ETBF: band 0(0x820ea000), band 1(0x820fa000), band 2(0x830ea000) */
#define MT_WF_ETBF_BASE(_band) __BASE(WF_ETBF_BASE, (_band))
#define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs))
#define MT_ETBF_RX_FB_CONT(_band) MT_WF_ETBF(_band, 0x100)
#define MT_ETBF_RX_FB_BW GENMASK(10, 8)
#define MT_ETBF_RX_FB_NC GENMASK(7, 4)
#define MT_ETBF_RX_FB_NR GENMASK(3, 0)
/* LPON: band 0(0x820eb000), band 1(0x820fb000), band 2(0x830eb000) */
#define MT_WF_LPON_BASE(_band) __BASE(WF_LPON_BASE, (_band))
#define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs))
#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, 0x360)
#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, 0x364)
#define MT_LPON_FRCR(_band) MT_WF_LPON(_band, 0x37c)
#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (((n) * 4) << 4))
#define MT_LPON_TCR_SW_MODE GENMASK(1, 0)
#define MT_LPON_TCR_SW_WRITE BIT(0)
#define MT_LPON_TCR_SW_ADJUST BIT(1)
#define MT_LPON_TCR_SW_READ GENMASK(1, 0)
/* MIB: band 0(0x820ed000), band 1(0x820fd000), band 2(0x830ed000)*/
/* These counters are (mostly?) clear-on-read. So, some should not
* be read at all in case firmware is already reading them. These
* are commented with 'DNR' below. The DNR stats will be read by querying
* the firmware API for the appropriate message. For counters the driver
* does read, the driver should accumulate the counters.
*/
#define MT_WF_MIB_BASE(_band) __BASE(WF_MIB_BASE, (_band))
#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs))
#define MT_MIB_BSCR0(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR0))
#define MT_MIB_BSCR1(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR1))
#define MT_MIB_BSCR2(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR2))
#define MT_MIB_BSCR3(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR3))
#define MT_MIB_BSCR4(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR4))
#define MT_MIB_BSCR5(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR5))
#define MT_MIB_BSCR6(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR6))
#define MT_MIB_BSCR7(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR7))
#define MT_MIB_BSCR17(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR17))
#define MT_MIB_TSCR5(_band) MT_WF_MIB(_band, 0x6c4)
#define MT_MIB_TSCR6(_band) MT_WF_MIB(_band, 0x6c8)
#define MT_MIB_TSCR7(_band) MT_WF_MIB(_band, 0x6d0)
#define MT_MIB_RSCR1(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR1))
/* rx mpdu counter, full 32 bits */
#define MT_MIB_RSCR31(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR31))
#define MT_MIB_RSCR33(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR33))
#define MT_MIB_SDR6(_band) MT_WF_MIB(_band, 0x020)
#define MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK GENMASK(15, 0)
#define MT_MIB_RVSR0(_band) MT_WF_MIB(_band, __OFFS(MIB_RVSR0))
#define MT_MIB_RSCR35(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR35))
#define MT_MIB_RSCR36(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR36))
/* tx ampdu cnt, full 32 bits */
#define MT_MIB_TSCR0(_band) MT_WF_MIB(_band, 0x6b0)
#define MT_MIB_TSCR2(_band) MT_WF_MIB(_band, 0x6b8)
/* counts all mpdus in ampdu, regardless of success */
#define MT_MIB_TSCR3(_band) MT_WF_MIB(_band, 0x6bc)
/* counts all successfully tx'd mpdus in ampdu */
#define MT_MIB_TSCR4(_band) MT_WF_MIB(_band, 0x6c0)
/* rx ampdu count, 32-bit */
#define MT_MIB_RSCR27(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR27))
/* rx ampdu bytes count, 32-bit */
#define MT_MIB_RSCR28(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR28))
/* rx ampdu valid subframe count */
#define MT_MIB_RSCR29(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR29))
/* rx ampdu valid subframe bytes count, 32bits */
#define MT_MIB_RSCR30(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR30))
/* remaining windows protected stats */
#define MT_MIB_SDR27(_band) MT_WF_MIB(_band, 0x080)
#define MT_MIB_SDR27_TX_RWP_FAIL_CNT GENMASK(15, 0)
#define MT_MIB_SDR28(_band) MT_WF_MIB(_band, 0x084)
#define MT_MIB_SDR28_TX_RWP_NEED_CNT GENMASK(15, 0)
#define MT_MIB_RVSR1(_band) MT_WF_MIB(_band, __OFFS(MIB_RVSR1))
/* rx blockack count, 32 bits */
#define MT_MIB_TSCR1(_band) MT_WF_MIB(_band, 0x6b4)
#define MT_MIB_BTSCR0(_band) MT_WF_MIB(_band, 0x5e0)
#define MT_MIB_BTSCR5(_band) MT_WF_MIB(_band, __OFFS(MIB_BTSCR5))
#define MT_MIB_BTSCR6(_band) MT_WF_MIB(_band, __OFFS(MIB_BTSCR6))
#define MT_MIB_BFTFCR(_band) MT_WF_MIB(_band, 0x5d0)
#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, __OFFS(MIB_TRDR1) + ((n) << 2))
#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2))
#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 4)) & GENMASK(9, 0))
/* UMIB */
#define MT_WF_UMIB_BASE 0x820cd000
#define MT_WF_UMIB(ofs) (MT_WF_UMIB_BASE + (ofs))
#define MT_UMIB_RPDCR(_band) (MT_WF_UMIB(0x594) + (_band) * 0x164)
/* WTBLON TOP */
#define MT_WTBLON_TOP_BASE 0x820d4000
#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs))
#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(__OFFS(WTBLON_WDUCR))
#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(4, 0)
#define MT_WTBL_UPDATE MT_WTBLON_TOP(__OFFS(WTBL_UPDATE))
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(11, 0)
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14)
#define MT_WTBL_UPDATE_BUSY BIT(31)
#define MT_WTBL_ITCR MT_WTBLON_TOP(__OFFS(WTBL_ITCR))
#define MT_WTBL_ITCR_WR BIT(16)
#define MT_WTBL_ITCR_EXEC BIT(31)
#define MT_WTBL_ITDR0 MT_WTBLON_TOP(__OFFS(WTBL_ITCR0))
#define MT_WTBL_ITDR1 MT_WTBLON_TOP(__OFFS(WTBL_ITCR1))
#define MT_WTBL_SPE_IDX_SEL BIT(6)
/* WTBL */
#define MT_WTBL_BASE 0x820d8000
#define MT_WTBL_LMAC_ID GENMASK(14, 8)
#define MT_WTBL_LMAC_DW GENMASK(7, 2)
#define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \
FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \
FIELD_PREP(MT_WTBL_LMAC_DW, _dw))
/* AGG: band 0(0x820e2000), band 1(0x820f2000), band 2(0x830e2000) */
#define MT_WF_AGG_BASE(_band) __BASE(WF_AGG_BASE, (_band))
#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
#define MT_AGG_ACR4(_band) MT_WF_AGG(_band, 0x3c)
#define MT_AGG_ACR_PPDU_TXS2H BIT(1)
/* ARB: band 0(0x820e3000), band 1(0x820f3000), band 2(0x830e3000) */
#define MT_WF_ARB_BASE(_band) __BASE(WF_ARB_BASE, (_band))
#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs))
#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x000)
#define MT_ARB_SCR_TX_DISABLE BIT(8)
#define MT_ARB_SCR_RX_DISABLE BIT(9)
/* RMAC: band 0(0x820e5000), band 1(0x820f5000), band 2(0x830e5000), */
#define MT_WF_RMAC_BASE(_band) __BASE(WF_RMAC_BASE, (_band))
#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs))
#define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000)
#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0)
#define MT_WF_RFCR_DROP_FCSFAIL BIT(1)
#define MT_WF_RFCR_DROP_PROBEREQ BIT(4)
#define MT_WF_RFCR_DROP_MCAST BIT(5)
#define MT_WF_RFCR_DROP_BCAST BIT(6)
#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7)
#define MT_WF_RFCR_DROP_A3_MAC BIT(8)
#define MT_WF_RFCR_DROP_A3_BSSID BIT(9)
#define MT_WF_RFCR_DROP_A2_BSSID BIT(10)
#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11)
#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12)
#define MT_WF_RFCR_DROP_CTL_RSV BIT(13)
#define MT_WF_RFCR_DROP_CTS BIT(14)
#define MT_WF_RFCR_DROP_RTS BIT(15)
#define MT_WF_RFCR_DROP_DUPLICATE BIT(16)
#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17)
#define MT_WF_RFCR_DROP_OTHER_UC BIT(18)
#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19)
#define MT_WF_RFCR_DROP_NDPA BIT(20)
#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21)
#define MT_WF_RFCR1(_band) MT_WF_RMAC(_band, 0x004)
#define MT_WF_RFCR1_DROP_ACK BIT(4)
#define MT_WF_RFCR1_DROP_BF_POLL BIT(5)
#define MT_WF_RFCR1_DROP_BA BIT(6)
#define MT_WF_RFCR1_DROP_CFEND BIT(7)
#define MT_WF_RFCR1_DROP_CFACK BIT(8)
#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380)
#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31)
#define MT_WF_RMAC_MIB_ED_OFFSET GENMASK(20, 16)
#define MT_WF_RMAC_MIB_OBSS_BACKOFF GENMASK(15, 0)
#define MT_WF_RMAC_MIB_AIRTIME1(_band) MT_WF_RMAC(_band, 0x0384)
#define MT_WF_RMAC_MIB_NONQOSD_BACKOFF GENMASK(31, 16)
#define MT_WF_RMAC_MIB_AIRTIME3(_band) MT_WF_RMAC(_band, 0x038c)
#define MT_WF_RMAC_MIB_QOS01_BACKOFF GENMASK(31, 0)
#define MT_WF_RMAC_MIB_AIRTIME4(_band) MT_WF_RMAC(_band, 0x0390)
#define MT_WF_RMAC_MIB_QOS23_BACKOFF GENMASK(31, 0)
#define MT_WF_RMAC_RSVD0(_band) MT_WF_RMAC(_band, 0x03e0)
#define MT_WF_RMAC_RSVD0_EIFS_CLR BIT(21)
/* RATE: band 0(0x820ee000), band 1(0x820fe000), band 2(0x830ee000) */
#define MT_WF_RATE_BASE(_band) __BASE(WF_RATE_BASE, (_band))
#define MT_WF_RATE(_band, ofs) (MT_WF_RATE_BASE(_band) + (ofs))
#define MT_RATE_HRCR0(_band) MT_WF_RATE(_band, 0x050)
#define MT_RATE_HRCR0_CFEND_RATE GENMASK(14, 0)
/* WFDMA0 */
#define MT_WFDMA0_BASE 0xd4000
#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs))
#define MT_WFDMA0_RST MT_WFDMA0(0x100)
#define MT_WFDMA0_RST_LOGIC_RST BIT(4)
#define MT_WFDMA0_RST_DMASHDL_ALL_RST BIT(5)
#define MT_WFDMA0_BUSY_ENA MT_WFDMA0(0x13c)
#define MT_WFDMA0_BUSY_ENA_TX_FIFO0 BIT(0)
#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1)
#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2)
#define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)
#define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3)
#define MT_WFDMA0_RX_INT_SEL_RING5 BIT(5)
#define MT_WFDMA0_RX_INT_SEL_RING6 BIT(6)
#define MT_WFDMA0_RX_INT_SEL_RING9 BIT(9)
#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208)
#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0)
#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
#define MT_WFDMA0_GLO_CFG_EXT_EN BIT(26)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27)
#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28)
#define MT_WFDMA0_PAUSE_RX_Q_45_TH MT_WFDMA0(0x268)
#define MT_WFDMA0_PAUSE_RX_Q_67_TH MT_WFDMA0(0x26c)
#define MT_WFDMA0_PAUSE_RX_Q_89_TH MT_WFDMA0(0x270)
#define MT_WFDMA0_PAUSE_RX_Q_RRO_TH MT_WFDMA0(0x27c)
#define WF_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
#define WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK GENMASK(27, 24)
#define WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD BIT(18)
#define WF_WFDMA0_GLO_CFG_EXT0_WED_MERGE_MODE BIT(14)
#define WF_WFDMA0_GLO_CFG_EXT1 MT_WFDMA0(0x2b4)
#define WF_WFDMA0_GLO_CFG_EXT1_CALC_MODE BIT(31)
#define WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE BIT(28)
#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c)
#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0)
#define MT_WFDMA0_PRI_DLY_INT_CFG1 MT_WFDMA0(0x2f4)
#define MT_WFDMA0_PRI_DLY_INT_CFG2 MT_WFDMA0(0x2f8)
/* WFDMA1 */
#define MT_WFDMA1_BASE 0xd5000
/* WFDMA CSR */
#define MT_WFDMA_EXT_CSR_BASE 0xd7000
#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs))
#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30)
#define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0)
#define MT_WFDMA_HOST_CONFIG_BAND0_PCIE1 BIT(20)
#define MT_WFDMA_HOST_CONFIG_BAND1_PCIE1 BIT(21)
#define MT_WFDMA_HOST_CONFIG_BAND2_PCIE1 BIT(22)
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
#define MT_WFDMA_AXI_R2A_CTRL MT_WFDMA_EXT_CSR(0x500)
#define MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK GENMASK(4, 0)
#define MT_WFDMA_AXI_R2A_CTRL2 MT_WFDMA_EXT_CSR(0x508)
#define MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK GENMASK(31, 28)
#define MT_PCIE_RECOG_ID 0xd7090
#define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0)
#define MT_PCIE_RECOG_ID_SEM BIT(31)
/* WFDMA0 PCIE1 */
#define MT_WFDMA0_PCIE1_BASE 0xd8000
#define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs))
#define MT_INT_PCIE1_SOURCE_CSR_EXT MT_WFDMA0_PCIE1(0x118)
#define MT_INT_PCIE1_MASK_CSR MT_WFDMA0_PCIE1(0x11c)
#define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c)
#define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0)
#define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1)
#define MT_WFDMA0_PCIE1_BUSY_ENA_RX_FIFO BIT(2)
/* WFDMA COMMON */
#define __RXQ(q) ((q) + __MT_MCUQ_MAX)
#define __TXQ(q) (__RXQ(q) + __MT_RXQ_MAX)
#define MT_Q_ID(q) (dev->q_id[(q)])
#define MT_Q_BASE(q) ((dev->q_wfdma_mask >> (q)) & 0x1 ? \
MT_WFDMA1_BASE : MT_WFDMA0_BASE)
#define MT_MCUQ_ID(q) MT_Q_ID(q)
#define MT_TXQ_ID(q) MT_Q_ID(__TXQ(q))
#define MT_RXQ_ID(q) MT_Q_ID(__RXQ(q))
#define MT_MCUQ_RING_BASE(q) (MT_Q_BASE(q) + 0x300)
#define MT_TXQ_RING_BASE(q) (MT_Q_BASE(__TXQ(q)) + 0x300)
#define MT_RXQ_RING_BASE(q) (MT_Q_BASE(__RXQ(q)) + 0x500)
#define MT_RXQ_RRO_IND_RING_BASE MT_RRO_TOP(0x40)
#define MT_RXQ_RRO_AP_RING_BASE MT_RRO_TOP(0x650)
#define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \
MT_MCUQ_ID(q) * 0x4)
#define MT_RXQ_EXT_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \
MT_RXQ_ID(q) * 0x4)
#define MT_TXQ_EXT_CTRL(q) (MT_Q_BASE(__TXQ(q)) + 0x600 + \
MT_TXQ_ID(q) * 0x4)
#define MT_INT_SOURCE_CSR MT_WFDMA0(0x200)
#define MT_INT_MASK_CSR MT_WFDMA0(0x204)
#define MT_INT1_SOURCE_CSR MT_WFDMA0_PCIE1(0x200)
#define MT_INT1_MASK_CSR MT_WFDMA0_PCIE1(0x204)
#define MT_INT_RX_DONE_BAND0 BIT(12)
#define MT_INT_RX_DONE_BAND1 BIT(13) /* for mt7992 */
#define MT_INT_RX_DONE_BAND2 BIT(13)
#define MT_INT_RX_DONE_WM BIT(0)
#define MT_INT_RX_DONE_WA BIT(1)
#define MT_INT_RX_DONE_WA_MAIN BIT(2)
#define MT_INT_RX_DONE_WA_EXT BIT(3) /* for mt7992 */
#define MT_INT_RX_DONE_WA_TRI BIT(3)
#define MT_INT_RX_TXFREE_MAIN BIT(17)
#define MT_INT_RX_TXFREE_BAND1 BIT(15)
#define MT_INT_RX_TXFREE_TRI BIT(15)
#define MT_INT_RX_TXFREE_BAND1_EXT BIT(19) /* for mt7992 two PCIE*/
#define MT_INT_RX_TXFREE_BAND0_MT7990 BIT(14)
#define MT_INT_RX_TXFREE_BAND1_MT7990 BIT(15)
#define MT_INT_RX_DONE_BAND2_EXT BIT(23)
#define MT_INT_RX_TXFREE_EXT BIT(26)
#define MT_INT_MCU_CMD BIT(29)
#define MT_INT_RX_DONE_RRO_BAND0 BIT(16)
#define MT_INT_RX_DONE_RRO_BAND1 BIT(17)
#define MT_INT_RX_DONE_RRO_BAND2 BIT(14)
#define MT_INT_RX_DONE_RRO_IND BIT(11)
#define MT_INT_RX_DONE_RRO_RXDMAD_C BIT(11)
#define MT_INT_RX_DONE_MSDU_PG_BAND0 BIT(18)
#define MT_INT_RX_DONE_MSDU_PG_BAND1 BIT(19)
#define MT_INT_RX_DONE_MSDU_PG_BAND2 BIT(23)
#define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)])
#define MT_INT_TX_MCU(q) (dev->q_int_mask[(q)])
#define MT_INT_RX_DONE_MCU (MT_INT_RX(MT_RXQ_MCU) | \
MT_INT_RX(MT_RXQ_MCU_WA))
#define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \
MT_INT_RX(MT_RXQ_MAIN_WA) | \
MT_INT_RX(MT_RXQ_TXFREE_BAND0))
#define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \
MT_INT_RX(MT_RXQ_BAND1_WA) | \
MT_INT_RX(MT_RXQ_MAIN_WA) | \
MT_INT_RX(MT_RXQ_TXFREE_BAND0))
#define MT_INT_BAND2_RX_DONE (MT_INT_RX(MT_RXQ_BAND2) | \
MT_INT_RX(MT_RXQ_BAND2_WA) | \
MT_INT_RX(MT_RXQ_MAIN_WA) | \
MT_INT_RX(MT_RXQ_TXFREE_BAND0))
#define MT_INT_RRO_RX_DONE (MT_INT_RX(MT_RXQ_RRO_BAND0) | \
MT_INT_RX(MT_RXQ_RRO_BAND1) | \
MT_INT_RX(MT_RXQ_RRO_BAND2) | \
MT_INT_RX(MT_RXQ_RRO_IND) | \
MT_INT_RX(MT_RXQ_RRO_RXDMAD_C) | \
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND0) | \
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND1) | \
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2))
#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \
MT_INT_BAND0_RX_DONE | \
MT_INT_BAND1_RX_DONE | \
MT_INT_BAND2_RX_DONE | \
MT_INT_RRO_RX_DONE)
#define MT_INT_TX_DONE_FWDL BIT(26)
#define MT_INT_TX_DONE_MCU_WM BIT(27)
#define MT_INT_TX_DONE_MCU_WA BIT(22)
#define MT_INT_TX_DONE_BAND0 BIT(30)
#define MT_INT_TX_DONE_BAND1 BIT(31)
#define MT_INT_TX_DONE_BAND2 BIT(15)
#define MT_INT_TX_RX_DONE_EXT (MT_INT_TX_DONE_BAND2 | \
MT_INT_RX_DONE_BAND2_EXT | \
MT_INT_RX_TXFREE_EXT)
#define MT_INT_TX_DONE_MCU (MT_INT_TX_MCU(MT_MCUQ_WA) | \
MT_INT_TX_MCU(MT_MCUQ_WM) | \
MT_INT_TX_MCU(MT_MCUQ_FWDL))
#define MT_MCU_CMD MT_WFDMA0(0x1f0)
#define MT_MCU_CMD_STOP_DMA BIT(2)
#define MT_MCU_CMD_RESET_DONE BIT(3)
#define MT_MCU_CMD_RECOVERY_DONE BIT(4)
#define MT_MCU_CMD_NORMAL_STATE BIT(5)
#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
#define MT_MCU_CMD_WA_WDT BIT(31)
#define MT_MCU_CMD_WM_WDT BIT(30)
#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30)
/* l1/l2 remap */
#define CONN_BUS_CR_VON_BASE 0x155000
#define MT_HIF_REMAP_L1 (CONN_BUS_CR_VON_BASE + __OFFS(HIF_REMAP_L1))
#define MT_HIF_REMAP_L1_MASK_7996 GENMASK(31, 16)
#define MT_HIF_REMAP_L1_MASK GENMASK(15, 0)
#define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0)
#define MT_HIF_REMAP_L1_BASE GENMASK(31, 16)
#define MT_HIF_REMAP_BASE_L1 __OFFS(HIF_REMAP_BASE_L1)
#define MT_HIF_REMAP_L2 __OFFS(HIF_REMAP_L2)
#define MT_HIF_REMAP_L2_MASK GENMASK(19, 0)
#define MT_HIF_REMAP_L2_OFFSET GENMASK(11, 0)
#define MT_HIF_REMAP_L2_BASE GENMASK(31, 12)
#define MT_HIF_REMAP_L2_MASK_7990 GENMASK(15, 0)
#define MT_HIF_REMAP_L2_OFFSET_7990 GENMASK(15, 0)
#define MT_HIF_REMAP_L2_BASE_7990 GENMASK(31, 16)
#define MT_HIF_REMAP_BASE_L2 __OFFS(HIF_REMAP_BASE_L2)
/* for mt7990 only */
#define MT_HIF_REMAP_CBTOP 0x1f6554
#define MT_HIF_REMAP_CBTOP_MASK GENMASK(15, 0)
#define MT_HIF_REMAP_CBTOP_OFFSET GENMASK(15, 0)
#define MT_HIF_REMAP_CBTOP_BASE GENMASK(31, 16)
#define MT_HIF_REMAP_BASE_CBTOP 0x1c0000
#define MT_INFRA_BASE 0x18000000
#define MT_WFSYS0_PHY_START 0x18400000
#define MT_WFSYS1_PHY_START 0x18800000
#define MT_WFSYS1_PHY_END 0x18bfffff
#define MT_CBTOP1_PHY_START 0x70000000
#define MT_CBTOP1_PHY_END __OFFS(CBTOP1_PHY_END)
#define MT_CBTOP2_PHY_START 0xf0000000
#define MT_INFRA_MCU_START 0x7c000000
#define MT_INFRA_MCU_END __OFFS(INFRA_MCU_END)
/* FW MODE SYNC */
#define MT_FW_ASSERT_CNT 0x02208274
#define MT_FW_DUMP_STATE 0x02209e90
#define MT_SWDEF_BASE 0x00401400
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
#define MT_SWDEF_MODE MT_SWDEF(0x3c)
#define MT_SWDEF_NORMAL_MODE 0
#define MT_SWDEF_SER_STATS MT_SWDEF(0x040)
#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044)
#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048)
#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04c)
#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050)
#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054)
#define MT_SWDEF_LAMC_WISR6_BN0_STATS MT_SWDEF(0x058)
#define MT_SWDEF_LAMC_WISR6_BN1_STATS MT_SWDEF(0x05c)
#define MT_SWDEF_LAMC_WISR6_BN2_STATS MT_SWDEF(0x060)
#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x064)
#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x068)
#define MT_SWDEF_LAMC_WISR7_BN2_STATS MT_SWDEF(0x06c)
/* LED */
#define MT_LED_TOP_BASE 0x18013000
#define MT_LED_PHYS(_n) (MT_LED_TOP_BASE + (_n))
#define MT_LED_CTRL(_n) MT_LED_PHYS(0x00 + ((_n) * 4))
#define MT_LED_CTRL_KICK BIT(7)
#define MT_LED_CTRL_BLINK_BAND_SEL BIT(4)
#define MT_LED_CTRL_BLINK_MODE BIT(2)
#define MT_LED_CTRL_POLARITY BIT(1)
#define MT_LED_TX_BLINK(_n) MT_LED_PHYS(0x10 + ((_n) * 4))
#define MT_LED_TX_BLINK_ON_MASK GENMASK(7, 0)
#define MT_LED_TX_BLINK_OFF_MASK GENMASK(15, 8)
#define MT_LED_EN(_n) MT_LED_PHYS(0x40 + ((_n) * 4))
/* CONN DBG */
#define MT_CONN_DBG_CTL_BASE 0x18023000
#define MT_CONN_DBG_CTL(ofs) (MT_CONN_DBG_CTL_BASE + (ofs))
#define MT_CONN_DBG_CTL_OUT_SEL MT_CONN_DBG_CTL(0x604)
#define MT_CONN_DBG_CTL_PC_LOG_SEL MT_CONN_DBG_CTL(0x60c)
#define MT_CONN_DBG_CTL_PC_LOG MT_CONN_DBG_CTL(0x610)
#define MT_LED_GPIO_MUX2 0x70005058 /* GPIO 18 */
#define MT_LED_GPIO_MUX3 0x7000505C /* GPIO 26 */
#define MT_LED_GPIO_SEL_MASK GENMASK(11, 8)
/* MT TOP */
#define MT_TOP_BASE 0xe0000
#define MT_TOP(ofs) (MT_TOP_BASE + (ofs))
#define MT_TOP_LPCR_HOST_BAND(_band) MT_TOP(0x10 + ((_band) * 0x10))
#define MT_TOP_LPCR_HOST_FW_OWN BIT(0)
#define MT_TOP_LPCR_HOST_DRV_OWN BIT(1)
#define MT_TOP_LPCR_HOST_FW_OWN_STAT BIT(2)
#define MT_TOP_LPCR_HOST_BAND_IRQ_STAT(_band) MT_TOP(0x14 + ((_band) * 0x10))
#define MT_TOP_LPCR_HOST_BAND_STAT BIT(0)
#define MT_TOP_MISC MT_TOP(0xf0)
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
/* ADIE */
#define MT_ADIE_CHIP_ID(_idx) (0x0f00002c + ((_idx) << 28))
#define MT_ADIE_VERSION_MASK GENMASK(15, 0)
#define MT_ADIE_CHIP_ID_MASK GENMASK(31, 16)
#define MT_PAD_GPIO 0x700056f0
#define MT_PAD_GPIO_ADIE_COMB GENMASK(16, 15)
#define MT_PAD_GPIO_2ADIE_TBTC BIT(19)
/* for mt7992 */
#define MT_PAD_GPIO_ADIE_COMB_7992 GENMASK(17, 16)
#define MT_PAD_GPIO_ADIE_SINGLE BIT(15)
#define MT_HW_REV 0x70010204
#define MT_HW_REV1 0x8a00
#define MT_WF_L05_RST 0x70028550
#define MT_WF_L05_RST_WF_RST_MASK GENMASK(4, 0)
#define MT_WF_SUBSYS_RST 0x70028600
#define MT_WF_SUBSYS_RST_WHOLE_PATH_RST BIT(0)
#define MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT BIT(5)
#define MT_WF_SUBSYS_RST_BYPASS_WFDMA_SLP_PROT BIT(6)
#define MT_WF_SUBSYS_RST_BYPASS_WFDMA2_SLP_PROT BIT(16)
#define MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT_CYCLE GENMASK(15, 8)
/* PCIE MAC */
#define MT_PCIE_MAC_BASE 0x74030000
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)
#define MT_PCIE1_MAC_BASE 0x74090000
#define MT_PCIE1_MAC(ofs) (MT_PCIE1_MAC_BASE + (ofs))
#define MT_PCIE1_MAC_INT_ENABLE MT_PCIE1_MAC(0x188)
/* PHYRX CSD */
#define MT_WF_PHYRX_CSD_BASE 0x83000000
#define MT_WF_PHYRX_CSD(_band, _wf, ofs) (MT_WF_PHYRX_CSD_BASE + \
((_band) << 20) + \
((_wf) << 16) + (ofs))
#define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
/* PHYRX CTRL */
#define MT_WF_PHYRX_BAND_BASE 0x83080000
#define MT_WF_PHYRX_BAND(_band, ofs) (MT_WF_PHYRX_BAND_BASE + \
((_band) << 20) + (ofs))
#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHYRX_BAND(_band, 0x1054)
#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHYRX_BAND(_band, 0x1058)
#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHYRX_BAND(_band, 0x105c)
#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHYRX_BAND(_band, 0x1060)
#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHYRX_BAND(_band, 0x1064)
#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHYRX_BAND(_band, 0x1068)
#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004)
#define MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN GENMASK(2, 0)
#define MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN GENMASK(11, 9)
/* PHYRX CSD BAND */
#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHYRX_BAND(_band, 0x8230)
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
/* CONN MCU EXCP CON */
#define MT_MCU_WM_EXCP_BASE 0x89050000
#define MT_MCU_WM_EXCP(ofs) (MT_MCU_WM_EXCP_BASE + (ofs))
#define MT_MCU_WM_EXCP_PC_CTRL MT_MCU_WM_EXCP(0x100)
#define MT_MCU_WM_EXCP_PC_LOG MT_MCU_WM_EXCP(0x104)
#define MT_MCU_WM_EXCP_LR_CTRL MT_MCU_WM_EXCP(0x200)
#define MT_MCU_WM_EXCP_LR_LOG MT_MCU_WM_EXCP(0x204)
/* CONN AFE CTL CON */
#define MT_AFE_CTL_BASE 0x18043000
#define MT_AFE_CTL_BAND(_band, ofs) (MT_AFE_CTL_BASE + \
((_band) * 0x1000) + (ofs))
#define MT_AFE_CTL_BAND_PLL_03(_band) MT_AFE_CTL_BAND(_band, 0x2c)
#define MT_AFE_CTL_BAND_PLL_03_MSB_EN BIT(1)
#endif