Skip to content
Permalink
Browse files
mt76: mt7915: add support for MT7986
This adds MT7986 SoC integrated multi-band 4x4 WiFi 6/6E.

Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
Bo Jiao authored and nbd168 committed Feb 14, 2022
1 parent 8450851 commit 91eeaef2523f3456f24a7dbdbf1e0e7deb133a48
Show file tree
Hide file tree
Showing 15 changed files with 1,810 additions and 80 deletions.
@@ -117,6 +117,11 @@ static inline bool is_mt7916(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7906;
}

static inline bool is_mt7986(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7986;
}

static inline bool is_mt7622(struct mt76_dev *dev)
{
if (!IS_ENABLED(CONFIG_MT7622_WMAC))
@@ -12,3 +12,13 @@ config MT7915E
OFDMA, spatial reuse and dual carrier modulation.

To compile this driver as a module, choose M here.

config MT7986_WMAC
bool "MT7986 (SoC) WMAC support"
depends on MT7915E
depends on ARCH_MEDIATEK || COMPILE_TEST
select REGMAP
help
This adds support for the built-in WMAC on MT7986 SoC device
which has the same feature set as a MT7915, but enables 6E
support.
@@ -6,3 +6,4 @@ mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
debugfs.o mmio.o

mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o
mt7915e-$(CONFIG_MT7986_WMAC) += soc.o
@@ -36,27 +36,48 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev)
switch (val) {
case 0x7915:
case 0x7916:
case 0x7986:
return 0;
default:
return -EINVAL;
}
}

static char *mt7915_eeprom_name(struct mt7915_dev *dev)
{
switch (mt76_chip(&dev->mt76)) {
case 0x7915:
return dev->dbdc_support ?
MT7915_EEPROM_DEFAULT_DBDC : MT7915_EEPROM_DEFAULT;
case 0x7986:
switch (mt7915_check_adie(dev, true)) {
case MT7976_ONE_ADIE_DBDC:
return MT7986_EEPROM_MT7976_DEFAULT_DBDC;
case MT7975_ONE_ADIE:
return MT7986_EEPROM_MT7975_DEFAULT;
case MT7976_ONE_ADIE:
return MT7986_EEPROM_MT7976_DEFAULT;
case MT7975_DUAL_ADIE:
return MT7986_EEPROM_MT7975_DUAL_DEFAULT;
case MT7976_DUAL_ADIE:
return MT7986_EEPROM_MT7976_DUAL_DEFAULT;
default:
break;
}
return NULL;
default:
return MT7916_EEPROM_DEFAULT;
}
}

static int
mt7915_eeprom_load_default(struct mt7915_dev *dev)
{
char *default_bin = MT7915_EEPROM_DEFAULT;
u8 *eeprom = dev->mt76.eeprom.data;
const struct firmware *fw = NULL;
int ret;

if (dev->dbdc_support)
default_bin = MT7915_EEPROM_DEFAULT_DBDC;

if (!is_mt7915(&dev->mt76))
default_bin = MT7916_EEPROM_DEFAULT;

ret = request_firmware(&fw, default_bin, dev->mt76.dev);
ret = request_firmware(&fw, mt7915_eeprom_name(dev), dev->mt76.dev);
if (ret)
return ret;

@@ -135,7 +156,7 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
struct mt7915_phy *phy)
{
u8 nss, nss_band, *eeprom = dev->mt76.eeprom.data;
u8 nss, nss_band, nss_band_max, *eeprom = dev->mt76.eeprom.data;
struct mt76_phy *mphy = phy->mt76;
bool ext_phy = phy != &dev->phy;

@@ -155,6 +176,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,

/* read tx/rx stream */
nss_band = nss;

if (dev->dbdc_support) {
if (is_mt7915(&dev->mt76)) {
nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
@@ -167,20 +189,29 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
eeprom[MT_EE_WIFI_CONF + 2 + ext_phy]);
}

if (!nss_band || nss_band > 2)
nss_band = 2;
nss_band_max = is_mt7986(&dev->mt76) ?
MT_EE_NSS_MAX_DBDC_MA7986 : MT_EE_NSS_MAX_DBDC_MA7915;
} else {
nss_band_max = is_mt7986(&dev->mt76) ?
MT_EE_NSS_MAX_MA7986 : MT_EE_NSS_MAX_MA7915;
}

if (!nss_band || nss_band > nss_band_max)
nss_band = nss_band_max;

if (nss_band > nss) {
dev_err(dev->mt76.dev,
"nss mismatch, nss(%d) nss_band(%d) ext_phy(%d)\n",
nss, nss_band, ext_phy);
dev_warn(dev->mt76.dev,
"nss mismatch, nss(%d) nss_band(%d) ext_phy(%d)\n",
nss, nss_band, ext_phy);
nss = nss_band;
}

mphy->chainmask = ext_phy ? (BIT(nss_band) - 1) << 2 : (BIT(nss_band) - 1);
mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1;
mphy->chainmask = BIT(nss) - 1;
if (ext_phy)
mphy->chainmask <<= dev->chainshift;
mphy->antenna_mask = BIT(nss_band) - 1;
dev->chainmask |= mphy->chainmask;
dev->chainshift = hweight8(dev->mphy.chainmask);
}

int mt7915_eeprom_init(struct mt7915_dev *dev)
@@ -226,7 +257,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,

if (chan->band == NL80211_BAND_2GHZ) {
u32 power = is_mt7915(&dev->mt76) ?
MT_EE_TX0_POWER_2G : MT_EE_TX0_POWER_2G_V2;
MT_EE_TX0_POWER_2G : MT_EE_TX0_POWER_2G_V2;

index = power + chain_idx * 3;
target_power = eeprom[index];
@@ -236,7 +267,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
} else {
int group = mt7915_get_channel_group(chan->hw_value);
u32 power = is_mt7915(&dev->mt76) ?
MT_EE_TX0_POWER_5G : MT_EE_TX0_POWER_5G_V2;
MT_EE_TX0_POWER_5G : MT_EE_TX0_POWER_5G_V2;

index = power + chain_idx * 12;
target_power = eeprom[index + group];
@@ -256,10 +287,10 @@ s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
u32 rate_2g, rate_5g;

rate_2g = is_mt7915(&dev->mt76) ?
MT_EE_RATE_DELTA_2G : MT_EE_RATE_DELTA_2G_V2;
MT_EE_RATE_DELTA_2G : MT_EE_RATE_DELTA_2G_V2;

rate_5g = is_mt7915(&dev->mt76) ?
MT_EE_RATE_DELTA_5G : MT_EE_RATE_DELTA_5G_V2;
MT_EE_RATE_DELTA_5G : MT_EE_RATE_DELTA_5G_V2;

if (band == NL80211_BAND_2GHZ)
val = eeprom[rate_2g];
@@ -56,6 +56,19 @@ enum mt7915_eeprom_field {
#define MT_EE_RATE_DELTA_SIGN BIT(6)
#define MT_EE_RATE_DELTA_EN BIT(7)

#define MT_EE_NSS_MAX_MA7915 4
#define MT_EE_NSS_MAX_DBDC_MA7915 2
#define MT_EE_NSS_MAX_MA7986 4
#define MT_EE_NSS_MAX_DBDC_MA7986 4

enum mt7915_adie_sku {
MT7976_ONE_ADIE_DBDC = 0x7,
MT7975_ONE_ADIE = 0x8,
MT7976_ONE_ADIE = 0xa,
MT7975_DUAL_ADIE = 0xd,
MT7976_DUAL_ADIE = 0xf,
};

enum mt7915_eeprom_band {
MT_EE_BAND_SEL_DEFAULT,
MT_EE_BAND_SEL_5GHZ,
@@ -582,6 +582,12 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev)
mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);

msleep(100);
} else if (is_mt7986(&dev->mt76)) {
mt7986_wmac_enable(dev);
msleep(20);

mt7986_wmac_disable(dev);
msleep(20);
} else {
mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);
msleep(20);
@@ -767,18 +773,25 @@ static int
mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
struct ieee80211_sband_iftype_data *data)
{
struct mt7915_dev *dev = phy->dev;
int i, idx = 0, nss = hweight8(phy->mt76->chainmask);
u16 mcs_map = 0;
u16 mcs_map_160 = 0;
u8 nss_160;

/* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
if (is_mt7915(&dev->mt76) && !dev->dbdc_support)
nss_160 = nss / 2;
else
nss_160 = nss;

for (i = 0; i < 8; i++) {
if (i < nss)
mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));
else
mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));

/* Can do 1/2 of NSS streams in 160Mhz mode. */
if (i < nss / 2)
if (i < nss_160)
mcs_map_160 |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));
else
mcs_map_160 |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
@@ -1011,5 +1024,8 @@ void mt7915_unregister_device(struct mt7915_dev *dev)
mt7915_dma_cleanup(dev);
tasklet_disable(&dev->irq_tasklet);

if (is_mt7986(&dev->mt76))
mt7986_wmac_disable(dev);

mt76_free_device(&dev->mt76);
}
@@ -1971,16 +1971,22 @@ mt7915_dma_reset(struct mt7915_dev *dev)
int i;

mt76_clear(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_clear(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN);

if (is_mt7915(&dev->mt76))
mt76_clear(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN);
if (dev->hif2) {
mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
(MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN));
mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
(MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN));
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN);

if (is_mt7915(&dev->mt76))
mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN);
}

usleep_range(1000, 2000);
@@ -2004,19 +2010,23 @@ mt7915_dma_reset(struct mt7915_dev *dev)

mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_set(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
if (dev->hif2) {
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
(MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN));
mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
(MT_WFDMA1_GLO_CFG_TX_DMA_EN |
if (is_mt7915(&dev->mt76))
mt76_set(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO));
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
if (dev->hif2) {
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN);

if (is_mt7915(&dev->mt76))
mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
}
}

@@ -969,12 +969,9 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)

phy->mt76->antenna_mask = tx_ant;

if (ext_phy) {
if (dev->chainmask == 0xf)
tx_ant <<= 2;
else
tx_ant <<= 1;
}
if (ext_phy)
tx_ant <<= dev->chainshift;

phy->mt76->chainmask = tx_ant;

mt76_set_stream_caps(phy->mt76, true);

0 comments on commit 91eeaef

Please sign in to comment.