]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: pci: update SER parameters for suspend/resume
authorPing-Ke Shih <pkshih@realtek.com>
Tue, 10 Mar 2026 08:01:35 +0000 (16:01 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Mon, 16 Mar 2026 06:12:49 +0000 (14:12 +0800)
In suspend mode, SER timer unit is different from normal mode. Set proper
value to prevent expected SER happened during suspend.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260310080146.31113-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/pci.h
drivers/net/wireless/realtek/rtw89/pci_be.c

index ccfa6d33623aa3c9b3a1cb0716c6cfafbcc860f8..dc488d9a8884f73819806c878ded42d6ad0ea64f 100644 (file)
 #define B_BE_PL1_IGNORE_HOT_RST BIT(30)
 #define B_BE_PL1_TIMER_UNIT_MASK GENMASK(19, 17)
 #define PCIE_SER_TIMER_UNIT 0x2
+#define PCIE_SER_WOW_TIMER_UNIT 0x4
 #define B_BE_PL1_TIMER_CLEAR BIT(0)
 
 #define R_BE_REG_PL1_MASK 0x34B0
index 114f40c6c31bc03d1440a2571e6aed4d84096082..dea01d9e57fd3c09c5a8cafb7d73fae8bed58788 100644 (file)
@@ -721,12 +721,24 @@ static int __maybe_unused rtw89_pci_suspend_be(struct device *dev)
 {
        struct ieee80211_hw *hw = dev_get_drvdata(dev);
        struct rtw89_dev *rtwdev = hw->priv;
+       u32 val32;
 
        rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
        rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_R_DIS_PRST);
        rtw89_write32_clr(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
        rtw89_write32_set(rtwdev, R_BE_PCIE_FRZ_CLK, B_BE_PCIE_FRZ_REG_RST);
-       rtw89_write32_clr(rtwdev, R_BE_REG_PL1_MASK, B_BE_SER_PM_MASTER_IMR);
+
+       val32 = rtw89_read32(rtwdev, R_BE_SER_PL1_CTRL);
+       if (val32 & B_BE_PL1_SER_PL1_EN) {
+               val32 = u32_replace_bits(val32, PCIE_SER_WOW_TIMER_UNIT,
+                                        B_BE_PL1_TIMER_UNIT_MASK);
+               rtw89_write32(rtwdev, R_BE_SER_PL1_CTRL, val32);
+
+               if (rtwdev->chip->chip_id == RTL8922A)
+                       rtw89_write32_clr(rtwdev, R_BE_REG_PL1_MASK,
+                                         B_BE_SER_PM_MASTER_IMR);
+       }
+
        return 0;
 }
 
@@ -735,12 +747,19 @@ static int __maybe_unused rtw89_pci_resume_be(struct device *dev)
        struct ieee80211_hw *hw = dev_get_drvdata(dev);
        struct rtw89_dev *rtwdev = hw->priv;
        u32 polling;
+       u32 val32;
+       u16 val16;
        int ret;
 
        rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
        rtw89_write32_clr(rtwdev, R_BE_RSV_CTRL, B_BE_R_DIS_PRST);
        rtw89_write32_clr(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
        rtw89_write32_clr(rtwdev, R_BE_PCIE_FRZ_CLK, B_BE_PCIE_FRZ_REG_RST);
+
+       val32 = rtw89_read32(rtwdev, R_BE_SER_PL1_CTRL);
+       if (!(val32 & B_BE_PL1_SER_PL1_EN))
+               goto clear_phy_isr;
+
        rtw89_write32_clr(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN);
 
        ret = read_poll_timeout_atomic(rtw89_read32, polling, !polling, 1, 1000,
@@ -748,8 +767,35 @@ static int __maybe_unused rtw89_pci_resume_be(struct device *dev)
        if (ret)
                rtw89_warn(rtwdev, "[ERR] PCIE SER clear polling fail\n");
 
-       rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN);
-       rtw89_write32_set(rtwdev, R_BE_REG_PL1_MASK, B_BE_SER_PM_MASTER_IMR);
+       if (rtwdev->chip->chip_id == RTL8922A)
+               rtw89_write32_set(rtwdev, R_BE_REG_PL1_MASK,
+                                 B_BE_SER_PM_MASTER_IMR | B_BE_SER_PCLKREQ_ACK_MASK);
+
+       val32 = rtw89_read32(rtwdev, R_BE_SER_PL1_CTRL);
+       val32 = u32_replace_bits(val32, PCIE_SER_TIMER_UNIT, B_BE_PL1_TIMER_UNIT_MASK);
+       val32 |= B_BE_PL1_SER_PL1_EN;
+       rtw89_write32(rtwdev, R_BE_SER_PL1_CTRL, val32);
+
+clear_phy_isr:
+       if (rtwdev->chip->chip_id == RTL8922D) {
+               val16 = rtw89_read16(rtwdev, RAC_DIRECT_OFFESET_L0_G2 +
+                                            RAC_ANA41 * RAC_MULT);
+               if (val16 & PHY_ERR_FLAG_EN) {
+                       rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G2 +
+                                                 RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+                       rtw89_write16_set(rtwdev, RAC_DIRECT_OFFESET_L0_G2 +
+                                                 RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+               }
+
+               val16 = rtw89_read16(rtwdev, RAC_DIRECT_OFFESET_L0_G1 +
+                                            RAC_ANA41 * RAC_MULT);
+               if (val16 & PHY_ERR_FLAG_EN) {
+                       rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G1 +
+                                                 RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+                       rtw89_write16_set(rtwdev, RAC_DIRECT_OFFESET_L0_G1 +
+                                                 RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+               }
+       }
 
        rtw89_pci_basic_cfg(rtwdev, true);