BRCM PCIe controller has different means of accessing to its own
config space and to device's config space. To support this quirk,
its driver uses simple heuristic:
when PCI subsystem probes Bus 0, the driver assumes
that the subsystem tries to accesses PCIe controller config space,
when PCI subsystem probes other busses, the driver uses mechanism
for device config space access. This heuristic works well when
there is only one PCIe controller in the system.
But U-Boot does not support concept of "PCI Segment", so when there
are more than one PCI controller:
- first one gets Bus address 0,
- second one - Bus address 2 and so on.
This breaks the brcm driver, because it tries to access second PCIe
controller config space as if it is device. To fix this, we introduce
additional property bus_base that holds a PCIe controller own Bus
address.
We use this property to calculate "real" Bus address for
underlying devices.
Please note that this fix may not support a case when we have
PCI-to-PCI bridges behind the second PCIe controller.

Signed-off-by: Oleksii Moisieiev <[email protected]>
Reviewed-by: Volodymyr Babchuk <[email protected]>
Signed-off-by: Torsten Duwe <[email protected]>
Reviewed-by: Oleksii Moisieiev <[email protected]>
---
 drivers/pci/pcie_brcmstb.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index f089c48f028..ca5951974ce 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -61,6 +61,7 @@ struct brcm_pcie {
 
        int                     gen;
        bool                    ssc;
+       uint16_t                bus_base;
 };
 
 /**
@@ -134,6 +135,7 @@ static int brcm_pcie_config_address(const struct udevice 
*dev, pci_dev_t bdf,
         * Busses 0 (host PCIe bridge) and 1 (its immediate child)
         * are limited to a single device each
         */
+       pci_bus -= pcie->bus_base;
        if (pci_bus < 2 && pci_dev > 0)
                return -EINVAL;
 
@@ -360,6 +362,8 @@ static int brcm_pcie_probe(struct udevice *dev)
        u16 nlw, cls, lnksta;
        u32 tmp;
 
+       pcie->bus_base = hose->first_busno;
+
        /*
         * Reset the bridge, assert the fundamental reset. Note for some SoCs,
         * e.g. BCM7278, the fundamental reset should not be asserted here.
-- 
2.51.0

Reply via email to