diff options
| author | Peter Chiu <chui-hao.chiu@mediatek.com> | 2026-03-12 12:57:21 +0300 |
|---|---|---|
| committer | Felix Fietkau <nbd@nbd.name> | 2026-03-24 18:49:31 +0300 |
| commit | 22f9abaf3656cf08d36196bab950668e7fc64381 (patch) | |
| tree | 4b97ce57238190b48990587547694435937a82fa | |
| parent | cf909557c1ba1215328db41f883ca5af5849f2fd (diff) | |
| download | linux-22f9abaf3656cf08d36196bab950668e7fc64381.tar.xz | |
wifi: mt76: mt7996: update WFSYS reset flow for MT7990 chipsets
Skip WFSYS reset during bootup for MT7990 chipsets; only reset if L0.5
recovery is triggered.
Without this fix, the following kernel error may occur:
Internal error: synchronous external abort.
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Link: https://patch.msgid.link/20260312095724.2117448-3-shayne.chen@mediatek.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/init.c | 29 | ||||
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/regs.h | 8 |
2 files changed, 34 insertions, 3 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index f3239f530aea..8dfb81eabc9a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -791,11 +791,34 @@ static void mt7996_init_work(struct work_struct *work) void mt7996_wfsys_reset(struct mt7996_dev *dev) { - mt76_set(dev, MT_WF_SUBSYS_RST, 0x1); - msleep(20); + if (!is_mt7990(&dev->mt76)) { + mt76_set(dev, MT_WF_SUBSYS_RST, 0x1); + msleep(20); + + mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1); + msleep(20); + + return; + } - mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1); + if (!dev->recovery.hw_full_reset) + return; + + mt76_set(dev, MT_WF_SUBSYS_RST, + MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT | + MT_WF_SUBSYS_RST_BYPASS_WFDMA_SLP_PROT | + MT_WF_SUBSYS_RST_BYPASS_WFDMA2_SLP_PROT); + mt76_rmw(dev, MT_WF_SUBSYS_RST, + MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT_CYCLE, + u32_encode_bits(0x20, MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT_CYCLE)); + mt76_clear(dev, MT_WF_L05_RST, MT_WF_L05_RST_WF_RST_MASK); + mt76_set(dev, MT_WF_SUBSYS_RST, MT_WF_SUBSYS_RST_WHOLE_PATH_RST); msleep(20); + + if (mt76_poll(dev, MT_WF_L05_RST, MT_WF_L05_RST_WF_RST_MASK, 0x1a, 1000)) + return; + + dev_err(dev->mt76.dev, "wfsys reset fail\n"); } static void mt7996_rro_hw_init_v3(struct mt7996_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 393faae2d52b..c6379933b6c3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -736,7 +736,15 @@ enum offs_rev { #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 |
