]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
PCI: mediatek-gen3: Fix PERST# control timing during system startup
authorJian Yang <jian.yang@mediatek.com>
Mon, 13 Apr 2026 07:13:55 +0000 (15:13 +0800)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 18 May 2026 17:34:46 +0000 (12:34 -0500)
Some MediaTek chips stop generating REFCLK if the PCIE_PHY_RSTB signal of
PCIe controller is asserted at the start of mtk_pcie_devices_power_up().

But the driver deasserts PCIE_PHY_RSTB together with PCIE_PE_RSTB signal
that is used to deassert PERST#. This violates PCIe CEM r6.0, sec 2.11.2,
which mandates waiting for 100ms (PCIE_T_PVPERL_MS) after power becomes
stable.

Move the MAC, PHY and BRG reset deassert code above the PCIE_T_PVPERL_MS
delay and leave the PCIE_PE_RSTB deassertion after the delay.

Add the 10ms delay mentioned in the MediaTek datasheet after asserting
PCIE_BRG_RSTB and before accessing the PCIE_RST_CTRL_REG register.

Signed-off-by: Jian Yang <jian.yang@mediatek.com>
[mani: commit log and comments rewording]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260413071401.1151-2-jian.yang@mediatek.com
drivers/pci/controller/pcie-mediatek-gen3.c

index b0accd82858921fd5ffeeab1d876e7f13e1d0208..01badc4f93119f8d794edd55bf6c496a5237545e 100644 (file)
 #define PCIE_BRG_RSTB                  BIT(2)
 #define PCIE_PE_RSTB                   BIT(3)
 
+/*
+ * As described in the datasheet of MediaTek PCIe Gen3 controller, wait 10ms
+ * after setting PCIE_BRG_RSTB, and before accessing PCIe internal registers.
+ */
+#define PCIE_BRG_RST_RDY_MS            10
+
 #define PCIE_LTSSM_STATUS_REG          0x150
 #define PCIE_LTSSM_STATE_MASK          GENMASK(28, 24)
 #define PCIE_LTSSM_STATE(val)          ((val & PCIE_LTSSM_STATE_MASK) >> 24)
@@ -430,6 +436,21 @@ static int mtk_pcie_devices_power_up(struct mtk_gen3_pcie *pcie)
                return err;
        }
 
+       /*
+        * Some of MediaTek's chips won't output REFCLK when PCIE_PHY_RSTB is
+        * asserted, we have to de-assert MAC & PHY & BRG reset signals first
+        * to allow the REFCLK to be stable. While PCIE_BRG_RSTB is asserted,
+        * there is a short period during which the PCIe internal register
+        * cannot be accessed, so we need to wait 10ms here.
+        */
+       msleep(PCIE_BRG_RST_RDY_MS);
+
+       if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
+               /* De-assert MAC, PHY and BRG reset signals */
+               val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB);
+               writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
+       }
+
        /*
         * Described in PCIe CEM specification revision 6.0.
         *
@@ -439,9 +460,8 @@ static int mtk_pcie_devices_power_up(struct mtk_gen3_pcie *pcie)
        msleep(PCIE_T_PVPERL_MS);
 
        if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
-               /* De-assert reset signals */
-               val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
-                        PCIE_PE_RSTB);
+               /* De-assert PERST# signal */
+               val &= ~PCIE_PE_RSTB;
                writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
        }