The PCIE SER is to diagnose PCIE becomes abnormal, relying on IMR settings to trigger interrupt when status is weird. Update settings to disable PHY error flag 9, and clear ISR when initial and leaving WoWLAN. Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/pci.h | 3 ++ drivers/net/wireless/realtek/rtw89/pci_be.c | 52 +++++++++++++++++---- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index dc488d9a8884..c7cd34e99349 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -55,6 +55,8 @@ #define B_AX_CALIB_EN BIT(13) #define B_AX_DIV GENMASK(15, 14) #define RAC_SET_PPR_V1 0x31 +#define RAC_ANA40 0x40 +#define PHY_ERR_IMR_DIS (BIT(9) | BIT(0)) #define RAC_ANA41 0x41 #define PHY_ERR_FLAG_EN BIT(6) @@ -1029,6 +1031,7 @@ #define B_BE_SER_PMU_IMR BIT(0) #define R_BE_REG_PL1_ISR 0x34B4 +#define B_PCIE_SER_ALL_ISR 0x7F #define R_BE_RX_APPEND_MODE 0x8920 #define B_BE_APPEND_OFFSET_MASK GENMASK(23, 16) diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c index dea01d9e57fd..dfffec1ff3c7 100644 --- a/drivers/net/wireless/realtek/rtw89/pci_be.c +++ b/drivers/net/wireless/realtek/rtw89/pci_be.c @@ -351,14 +351,41 @@ static void rtw89_pci_ser_setting_be(struct rtw89_dev *rtwdev) return; rtw89_write32(rtwdev, R_BE_PL1_DBG_INFO, 0x0); - rtw89_write32_set(rtwdev, R_BE_FWS1IMR, B_BE_PCIE_SER_TIMEOUT_INDIC_EN); - rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN); - rtw89_write32_mask(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_TIMER_UNIT_MASK, 1); - val32 = rtw89_read32(rtwdev, R_BE_REG_PL1_MASK); - val32 |= B_BE_SER_PMU_IMR | B_BE_SER_L1SUB_IMR | B_BE_SER_PM_MASTER_IMR | - B_BE_SER_LTSSM_IMR | B_BE_SER_PM_CLK_MASK | B_BE_SER_PCLKREQ_ACK_MASK; - rtw89_write32(rtwdev, R_BE_REG_PL1_MASK, val32); + switch (hal->cv) { + case CHIP_CAV: + case CHIP_CBV: + rtw89_write32_clr(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN); + rtw89_write32_mask(rtwdev, R_BE_SER_PL1_CTRL, + B_BE_PL1_TIMER_UNIT_MASK, PCIE_SER_TIMER_UNIT); + + val32 = rtw89_read32(rtwdev, R_BE_REG_PL1_MASK); + val32 &= ~(B_BE_SER_PMU_IMR | B_BE_SER_L1SUB_IMR | + B_BE_SER_PM_MASTER_IMR | B_BE_SER_LTSSM_IMR | + B_BE_SER_PM_CLK_MASK | B_BE_SER_PCLKREQ_ACK_MASK); + rtw89_write32(rtwdev, R_BE_REG_PL1_MASK, val32); + break; + case CHIP_CCV: + default: + rtw89_write32_clr(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN); + + ret = read_poll_timeout_atomic(rtw89_read32, val32, !val32, + 1, 1000, false, rtwdev, R_BE_REG_PL1_ISR); + if (ret) + rtw89_warn(rtwdev, "[ERR] PCIE SER clear poll fail\n"); + + rtw89_write32_mask(rtwdev, R_BE_SER_PL1_CTRL, + B_BE_PL1_TIMER_UNIT_MASK, PCIE_SER_TIMER_UNIT); + rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN); + + val32 = rtw89_read32(rtwdev, R_BE_REG_PL1_MASK); + val32 |= (B_BE_SER_PMU_IMR | B_BE_SER_PM_MASTER_IMR | + B_BE_SER_LTSSM_IMR | B_BE_SER_PM_CLK_MASK | + B_BE_SER_PCLKREQ_ACK_MASK); + val32 &= ~B_BE_SER_L1SUB_IMR; + rtw89_write32(rtwdev, R_BE_REG_PL1_MASK, val32); + break; + } return; @@ -366,6 +393,11 @@ static void rtw89_pci_ser_setting_be(struct rtw89_dev *rtwdev) rtw89_write32_clr(rtwdev, R_BE_PCIE_SER_DBG, B_BE_PCIE_SER_FLUSH_RSTB); rtw89_write32_set(rtwdev, R_BE_PCIE_SER_DBG, B_BE_PCIE_SER_FLUSH_RSTB); + rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G1 + + RAC_ANA40 * RAC_MULT, PHY_ERR_IMR_DIS); + rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G2 + + RAC_ANA40 * RAC_MULT, PHY_ERR_IMR_DIS); + rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G1 + RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN); rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G2 + @@ -378,6 +410,7 @@ static void rtw89_pci_ser_setting_be(struct rtw89_dev *rtwdev) val32 = rtw89_read32(rtwdev, R_BE_SER_PL1_CTRL); val32 &= ~B_BE_PL1_SER_PL1_EN; rtw89_write32(rtwdev, R_BE_SER_PL1_CTRL, val32); + rtw89_write32(rtwdev, R_BE_REG_PL1_ISR, B_PCIE_SER_ALL_ISR); ret = read_poll_timeout_atomic(rtw89_read32, val32, !val32, 1, 1000, false, rtwdev, R_BE_REG_PL1_ISR); @@ -385,9 +418,10 @@ static void rtw89_pci_ser_setting_be(struct rtw89_dev *rtwdev) rtw89_warn(rtwdev, "[ERR] PCIE SER clear poll fail\n"); val32 = rtw89_read32(rtwdev, R_BE_REG_PL1_MASK); - val32 |= B_BE_SER_PMU_IMR | B_BE_SER_L1SUB_IMR | B_BE_SER_PM_MASTER_IMR | + val32 |= B_BE_SER_PMU_IMR | B_BE_SER_PM_MASTER_IMR | B_BE_SER_LTSSM_IMR | B_BE_SER_PM_CLK_MASK | B_BE_SER_PCLKREQ_ACK_MASK | B_BE_SER_LTSSM_UNSTABLE_MASK; + val32 &= ~B_BE_SER_L1SUB_IMR; rtw89_write32(rtwdev, R_BE_REG_PL1_MASK, val32); rtw89_write32_mask(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_TIMER_UNIT_MASK, @@ -761,6 +795,8 @@ static int __maybe_unused rtw89_pci_resume_be(struct device *dev) goto clear_phy_isr; rtw89_write32_clr(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN); + if (rtwdev->chip->chip_id == RTL8922D) + rtw89_write32(rtwdev, R_BE_REG_PL1_ISR, B_PCIE_SER_ALL_ISR); ret = read_poll_timeout_atomic(rtw89_read32, polling, !polling, 1, 1000, false, rtwdev, R_BE_REG_PL1_ISR); -- 2.25.1