]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
PCI: brcmstb: Set MLW based on "num-lanes" DT property if present
authorJim Quinlan <james.quinlan@broadcom.com>
Mon, 5 Jan 2026 17:34:19 +0000 (12:34 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 09:15:04 +0000 (10:15 +0100)
[ Upstream commit a364d10ffe361fb34c3838d33604da493045de1e ]

By default, the driver relies on the default hardware defined value for the
Max Link Width (MLW) capability. But if the "num-lanes" DT property is
present, assume that the chip's default capability information is incorrect
or undesired, and use the specified value instead.

Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
[mani: reworded the description and comments]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20250530224035.41886-3-james.quinlan@broadcom.com
Stable-dep-of: 9583f9d22991 ("PCI: brcmstb: Fix disabling L0s capability")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/pci/controller/pcie-brcmstb.c

index 62e1d661ee0b579cf46db0d34fbbd459b848a8ac..29f0da00c7297a64c0ce7d77b8b481e7b82bdadd 100644 (file)
@@ -46,6 +46,7 @@
 #define  PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK     0xffffff
 
 #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY                      0x04dc
+#define  PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK 0x1f0
 #define  PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK   0xc00
 
 #define PCIE_RC_CFG_PRIV1_ROOT_CAP                     0x4f8
@@ -55,6 +56,9 @@
 #define PCIE_RC_DL_MDIO_WR_DATA                                0x1104
 #define PCIE_RC_DL_MDIO_RD_DATA                                0x1108
 
+#define PCIE_RC_PL_REG_PHY_CTL_1                       0x1804
+#define  PCIE_RC_PL_REG_PHY_CTL_1_REG_P2_POWERDOWN_ENA_NOSYNC_MASK     0x8
+
 #define PCIE_MISC_MISC_CTRL                            0x4008
 #define  PCIE_MISC_MISC_CTRL_PCIE_RCB_64B_MODE_MASK    0x80
 #define  PCIE_MISC_MISC_CTRL_PCIE_RCB_MPS_MODE_MASK    0x400
@@ -1025,7 +1029,7 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
        void __iomem *base = pcie->base;
        struct pci_host_bridge *bridge;
        struct resource_entry *entry;
-       u32 tmp, burst, aspm_support;
+       u32 tmp, burst, aspm_support, num_lanes, num_lanes_cap;
        u8 num_out_wins = 0;
        int num_inbound_wins = 0;
        int memc, ret;
@@ -1133,6 +1137,27 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
                PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
        writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
 
+       /* 'tmp' still holds the contents of PRIV1_LINK_CAPABILITY */
+       num_lanes_cap = u32_get_bits(tmp, PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK);
+       num_lanes = 0;
+
+       /*
+        * Use hardware negotiated Max Link Width value by default.  If the
+        * "num-lanes" DT property is present, assume that the chip's default
+        * link width capability information is incorrect/undesired and use the
+        * specified value instead.
+        */
+       if (!of_property_read_u32(pcie->np, "num-lanes", &num_lanes) &&
+           num_lanes && num_lanes <= 4 && num_lanes_cap != num_lanes) {
+               u32p_replace_bits(&tmp, num_lanes,
+                       PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK);
+               writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
+               tmp = readl(base + PCIE_RC_PL_REG_PHY_CTL_1);
+               u32p_replace_bits(&tmp, 1,
+                       PCIE_RC_PL_REG_PHY_CTL_1_REG_P2_POWERDOWN_ENA_NOSYNC_MASK);
+               writel(tmp, base + PCIE_RC_PL_REG_PHY_CTL_1);
+       }
+
        /*
         * For config space accesses on the RC, show the right class for
         * a PCIe-PCIe bridge (the default setting is to be EP mode).