PCI: brcmstb: Split post-link up initialization to brcm_pcie_start_link()
authorJim Quinlan <jim2101024@gmail.com>
Mon, 25 Jul 2022 15:12:51 +0000 (11:12 -0400)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 27 Jul 2022 16:52:59 +0000 (11:52 -0500)
Previously brcm_pcie_setup() initialized the Root Port itself as well as
doing the actual link-up.  Split brcm_pcie_setup() into two functions:

  - brcm_pcie_setup(), which initializes everything that does not require
    the link itself to be up, and

  - brcm_pcie_start_link(), which brings up the link and initializes things
    that depend on the link being up.

[bhelgaas: condense commit log, deferring details for future changes]
Link: https://lore.kernel.org/r/20220725151258.42574-3-jim2101024@gmail.com
Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
drivers/pci/controller/pcie-brcmstb.c

index 52a53c4..56631d4 100644 (file)
@@ -857,17 +857,13 @@ static inline int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
 
 static int brcm_pcie_setup(struct brcm_pcie *pcie)
 {
-       struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
        u64 rc_bar2_offset, rc_bar2_size;
        void __iomem *base = pcie->base;
-       struct device *dev = pcie->dev;
+       struct pci_host_bridge *bridge;
        struct resource_entry *entry;
-       bool ssc_good = false;
-       struct resource *res;
-       int num_out_wins = 0;
-       u16 nlw, cls, lnksta;
-       int i, ret, memc;
        u32 tmp, burst, aspm_support;
+       int num_out_wins = 0;
+       int ret, memc;
 
        /* Reset the bridge */
        pcie->bridge_sw_init_set(pcie, 1);
@@ -943,6 +939,11 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
        else
                pcie->msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB;
 
+       if (!brcm_pcie_rc_mode(pcie)) {
+               dev_err(pcie->dev, "PCIe RC controller misconfigured as Endpoint\n");
+               return -EINVAL;
+       }
+
        /* disable the PCIe->GISB memory window (RC_BAR1) */
        tmp = readl(base + PCIE_MISC_RC_BAR1_CONFIG_LO);
        tmp &= ~PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK;
@@ -953,31 +954,27 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
        tmp &= ~PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK;
        writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
 
-       if (pcie->gen)
-               brcm_pcie_set_gen(pcie, pcie->gen);
-
-       /* Unassert the fundamental reset */
-       pcie->perst_set(pcie, 0);
+       /* Don't advertise L0s capability if 'aspm-no-l0s' */
+       aspm_support = PCIE_LINK_STATE_L1;
+       if (!of_property_read_bool(pcie->np, "aspm-no-l0s"))
+               aspm_support |= PCIE_LINK_STATE_L0S;
+       tmp = readl(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
+       u32p_replace_bits(&tmp, aspm_support,
+               PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
+       writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
 
        /*
-        * Give the RC/EP time to wake up, before trying to configure RC.
-        * Intermittently check status for link-up, up to a total of 100ms.
+        * For config space accesses on the RC, show the right class for
+        * a PCIe-PCIe bridge (the default setting is to be EP mode).
         */
-       for (i = 0; i < 100 && !brcm_pcie_link_up(pcie); i += 5)
-               msleep(5);
-
-       if (!brcm_pcie_link_up(pcie)) {
-               dev_err(dev, "link down\n");
-               return -ENODEV;
-       }
-
-       if (!brcm_pcie_rc_mode(pcie)) {
-               dev_err(dev, "PCIe misconfigured; is in EP mode\n");
-               return -EINVAL;
-       }
+       tmp = readl(base + PCIE_RC_CFG_PRIV1_ID_VAL3);
+       u32p_replace_bits(&tmp, 0x060400,
+                         PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK);
+       writel(tmp, base + PCIE_RC_CFG_PRIV1_ID_VAL3);
 
+       bridge = pci_host_bridge_from_priv(pcie);
        resource_list_for_each_entry(entry, &bridge->windows) {
-               res = entry->res;
+               struct resource *res = entry->res;
 
                if (resource_type(res) != IORESOURCE_MEM)
                        continue;
@@ -1006,23 +1003,41 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
                num_out_wins++;
        }
 
-       /* Don't advertise L0s capability if 'aspm-no-l0s' */
-       aspm_support = PCIE_LINK_STATE_L1;
-       if (!of_property_read_bool(pcie->np, "aspm-no-l0s"))
-               aspm_support |= PCIE_LINK_STATE_L0S;
-       tmp = readl(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
-       u32p_replace_bits(&tmp, aspm_support,
-               PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
-       writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
+       /* PCIe->SCB endian mode for BAR */
+       tmp = readl(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
+       u32p_replace_bits(&tmp, PCIE_RC_CFG_VENDOR_SPCIFIC_REG1_LITTLE_ENDIAN,
+               PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK);
+       writel(tmp, base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
+
+       return 0;
+}
+
+static int brcm_pcie_start_link(struct brcm_pcie *pcie)
+{
+       struct device *dev = pcie->dev;
+       void __iomem *base = pcie->base;
+       u16 nlw, cls, lnksta;
+       bool ssc_good = false;
+       u32 tmp;
+       int ret, i;
+
+       /* Unassert the fundamental reset */
+       pcie->perst_set(pcie, 0);
 
        /*
-        * For config space accesses on the RC, show the right class for
-        * a PCIe-PCIe bridge (the default setting is to be EP mode).
+        * Give the RC/EP time to wake up, before trying to configure RC.
+        * Intermittently check status for link-up, up to a total of 100ms.
         */
-       tmp = readl(base + PCIE_RC_CFG_PRIV1_ID_VAL3);
-       u32p_replace_bits(&tmp, 0x060400,
-                         PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK);
-       writel(tmp, base + PCIE_RC_CFG_PRIV1_ID_VAL3);
+       for (i = 0; i < 100 && !brcm_pcie_link_up(pcie); i += 5)
+               msleep(5);
+
+       if (!brcm_pcie_link_up(pcie)) {
+               dev_err(dev, "link down\n");
+               return -ENODEV;
+       }
+
+       if (pcie->gen)
+               brcm_pcie_set_gen(pcie, pcie->gen);
 
        if (pcie->ssc) {
                ret = brcm_pcie_set_ssc(pcie);
@@ -1039,12 +1054,6 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
                 pci_speed_string(pcie_link_speed[cls]), nlw,
                 ssc_good ? "(SSC)" : "(!SSC)");
 
-       /* PCIe->SCB endian mode for BAR */
-       tmp = readl(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
-       u32p_replace_bits(&tmp, PCIE_RC_CFG_VENDOR_SPCIFIC_REG1_LITTLE_ENDIAN,
-               PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK);
-       writel(tmp, base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
-
        /*
         * Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
         * is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1.
@@ -1212,6 +1221,10 @@ static int brcm_pcie_resume(struct device *dev)
        if (ret)
                goto err_reset;
 
+       ret = brcm_pcie_start_link(pcie);
+       if (ret)
+               goto err_reset;
+
        if (pcie->msi)
                brcm_msi_set_regs(pcie->msi);
 
@@ -1401,6 +1414,10 @@ static int brcm_pcie_probe(struct platform_device *pdev)
        if (ret)
                goto fail;
 
+       ret = brcm_pcie_start_link(pcie);
+       if (ret)
+               goto fail;
+
        pcie->hw_rev = readl(pcie->base + PCIE_MISC_REVISION);
        if (pcie->type == BCM4908 && pcie->hw_rev >= BRCM_PCIE_HW_REV_3_20) {
                dev_err(pcie->dev, "hardware revision with unsupported PERST# setup\n");