PCI: brcmstb: Split post-link up initialization to brcm_pcie_start_link()
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>
This commit is contained in:
parent
5fb8f2628e
commit
0693b4207f
|
@ -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)
|
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;
|
u64 rc_bar2_offset, rc_bar2_size;
|
||||||
void __iomem *base = pcie->base;
|
void __iomem *base = pcie->base;
|
||||||
struct device *dev = pcie->dev;
|
struct pci_host_bridge *bridge;
|
||||||
struct resource_entry *entry;
|
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;
|
u32 tmp, burst, aspm_support;
|
||||||
|
int num_out_wins = 0;
|
||||||
|
int ret, memc;
|
||||||
|
|
||||||
/* Reset the bridge */
|
/* Reset the bridge */
|
||||||
pcie->bridge_sw_init_set(pcie, 1);
|
pcie->bridge_sw_init_set(pcie, 1);
|
||||||
|
@ -943,6 +939,11 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
|
||||||
else
|
else
|
||||||
pcie->msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB;
|
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) */
|
/* disable the PCIe->GISB memory window (RC_BAR1) */
|
||||||
tmp = readl(base + PCIE_MISC_RC_BAR1_CONFIG_LO);
|
tmp = readl(base + PCIE_MISC_RC_BAR1_CONFIG_LO);
|
||||||
tmp &= ~PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK;
|
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;
|
tmp &= ~PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK;
|
||||||
writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
|
writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
|
||||||
|
|
||||||
if (pcie->gen)
|
/* Don't advertise L0s capability if 'aspm-no-l0s' */
|
||||||
brcm_pcie_set_gen(pcie, pcie->gen);
|
aspm_support = PCIE_LINK_STATE_L1;
|
||||||
|
if (!of_property_read_bool(pcie->np, "aspm-no-l0s"))
|
||||||
/* Unassert the fundamental reset */
|
aspm_support |= PCIE_LINK_STATE_L0S;
|
||||||
pcie->perst_set(pcie, 0);
|
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.
|
* For config space accesses on the RC, show the right class for
|
||||||
* Intermittently check status for link-up, up to a total of 100ms.
|
* a PCIe-PCIe bridge (the default setting is to be EP mode).
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < 100 && !brcm_pcie_link_up(pcie); i += 5)
|
tmp = readl(base + PCIE_RC_CFG_PRIV1_ID_VAL3);
|
||||||
msleep(5);
|
u32p_replace_bits(&tmp, 0x060400,
|
||||||
|
PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK);
|
||||||
if (!brcm_pcie_link_up(pcie)) {
|
writel(tmp, base + PCIE_RC_CFG_PRIV1_ID_VAL3);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
bridge = pci_host_bridge_from_priv(pcie);
|
||||||
resource_list_for_each_entry(entry, &bridge->windows) {
|
resource_list_for_each_entry(entry, &bridge->windows) {
|
||||||
res = entry->res;
|
struct resource *res = entry->res;
|
||||||
|
|
||||||
if (resource_type(res) != IORESOURCE_MEM)
|
if (resource_type(res) != IORESOURCE_MEM)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1006,23 +1003,41 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
|
||||||
num_out_wins++;
|
num_out_wins++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't advertise L0s capability if 'aspm-no-l0s' */
|
/* PCIe->SCB endian mode for BAR */
|
||||||
aspm_support = PCIE_LINK_STATE_L1;
|
tmp = readl(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
|
||||||
if (!of_property_read_bool(pcie->np, "aspm-no-l0s"))
|
u32p_replace_bits(&tmp, PCIE_RC_CFG_VENDOR_SPCIFIC_REG1_LITTLE_ENDIAN,
|
||||||
aspm_support |= PCIE_LINK_STATE_L0S;
|
PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK);
|
||||||
tmp = readl(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
|
writel(tmp, base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
|
||||||
u32p_replace_bits(&tmp, aspm_support,
|
|
||||||
PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
|
return 0;
|
||||||
writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
|
}
|
||||||
|
|
||||||
|
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
|
* Give the RC/EP time to wake up, before trying to configure RC.
|
||||||
* a PCIe-PCIe bridge (the default setting is to be EP mode).
|
* Intermittently check status for link-up, up to a total of 100ms.
|
||||||
*/
|
*/
|
||||||
tmp = readl(base + PCIE_RC_CFG_PRIV1_ID_VAL3);
|
for (i = 0; i < 100 && !brcm_pcie_link_up(pcie); i += 5)
|
||||||
u32p_replace_bits(&tmp, 0x060400,
|
msleep(5);
|
||||||
PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK);
|
|
||||||
writel(tmp, base + PCIE_RC_CFG_PRIV1_ID_VAL3);
|
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) {
|
if (pcie->ssc) {
|
||||||
ret = brcm_pcie_set_ssc(pcie);
|
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,
|
pci_speed_string(pcie_link_speed[cls]), nlw,
|
||||||
ssc_good ? "(SSC)" : "(!SSC)");
|
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
|
* Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
|
||||||
* is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1.
|
* is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1.
|
||||||
|
@ -1212,6 +1221,10 @@ static int brcm_pcie_resume(struct device *dev)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_reset;
|
goto err_reset;
|
||||||
|
|
||||||
|
ret = brcm_pcie_start_link(pcie);
|
||||||
|
if (ret)
|
||||||
|
goto err_reset;
|
||||||
|
|
||||||
if (pcie->msi)
|
if (pcie->msi)
|
||||||
brcm_msi_set_regs(pcie->msi);
|
brcm_msi_set_regs(pcie->msi);
|
||||||
|
|
||||||
|
@ -1401,6 +1414,10 @@ static int brcm_pcie_probe(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
ret = brcm_pcie_start_link(pcie);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
pcie->hw_rev = readl(pcie->base + PCIE_MISC_REVISION);
|
pcie->hw_rev = readl(pcie->base + PCIE_MISC_REVISION);
|
||||||
if (pcie->type == BCM4908 && pcie->hw_rev >= BRCM_PCIE_HW_REV_3_20) {
|
if (pcie->type == BCM4908 && pcie->hw_rev >= BRCM_PCIE_HW_REV_3_20) {
|
||||||
dev_err(pcie->dev, "hardware revision with unsupported PERST# setup\n");
|
dev_err(pcie->dev, "hardware revision with unsupported PERST# setup\n");
|
||||||
|
|
Loading…
Reference in New Issue