[PATCH 03/11] pci: xilinx: Add probe function and improve memory region handling
Uros Stajic
uros.stajic at htecgroup.com
Tue Jun 3 15:39:04 CEST 2025
From: Chao-ying Fu <cfu at mips.com>
This patch adds a `.probe` implementation to the Xilinx PCIe driver
to initializ bridge registers and determine the ECAM region size
at runtime.
Additionally, writing the PCI memory base and limit registers is skipped
for the root bridge (bus 0, device 0). On platforms such as the MIPS
Boston board, writing these fields results in incorrect values being
reported (e.g. base = 0x0, limit = 0x1600), causing Linux to fail
memory space assignment for the bridge.
This workaround allows a MIPS Boston board to boot Linux & let Linux
successfully probe the PCIe bus & all devices connected to it.
Signed-off-by: Chao-ying Fu <cfu at mips.com>
Signed-off-by: Uros Stajic <uros.stajic at htecgroup.com>
---
drivers/pci/pcie_xilinx.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c
index 63058e8e7c5..3b6a8ced848 100644
--- a/drivers/pci/pcie_xilinx.c
+++ b/drivers/pci/pcie_xilinx.c
@@ -132,6 +132,15 @@ static int pcie_xilinx_write_config(struct udevice *bus, pci_dev_t bdf,
uint offset, ulong value,
enum pci_size_t size)
{
+ if (bdf == PCI_BDF(bus->seq_, 0, 0)) {
+ switch (offset) {
+ case PCI_MEMORY_BASE:
+ case PCI_MEMORY_LIMIT:
+ /* Writing the memory base or limit causes problems */
+ return 0;
+ }
+ }
+
return pci_generic_mmap_write_config(bus, pcie_xilinx_config_address,
bdf, offset, value, size);
}
@@ -186,6 +195,31 @@ static int pci_xilinx_probe(struct udevice *dev)
return 0;
}
+static int pcie_xilinx_probe(struct udevice *dev)
+{
+ struct xilinx_pcie *pcie = dev_get_priv(dev);
+ u32 bridge_info, ecam_sz, rpsc;
+
+ /* Disable all interrupts */
+ writel(0, pcie->cfg_base + XILINX_PCIE_REG_INT_MASK);
+
+ /* Enable the bridge */
+ rpsc = readl(pcie->cfg_base + XILINX_PCIE_REG_RPSC);
+ rpsc |= XILINX_PCIE_REG_RPSC_BEN;
+ writel(rpsc, pcie->cfg_base + XILINX_PCIE_REG_RPSC);
+
+ /* Discover the size of the ECAM region */
+ bridge_info = readl(pcie->cfg_base + XILINX_PCIE_REG_BRIDGE_INFO);
+ ecam_sz = bridge_info & XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_MASK;
+ ecam_sz >>= XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_SHIFT;
+
+ /* Enable access to all possible subordinate buses */
+ writel((0 << 0) | (1 << 8) | (GENMASK(ecam_sz - 1, 0) << 16),
+ pcie->cfg_base + PCI_PRIMARY_BUS);
+
+ return 0;
+}
+
static const struct dm_pci_ops pcie_xilinx_ops = {
.read_config = pcie_xilinx_read_config,
.write_config = pcie_xilinx_write_config,
@@ -204,4 +238,5 @@ U_BOOT_DRIVER(pcie_xilinx) = {
.of_to_plat = pcie_xilinx_of_to_plat,
.probe = pci_xilinx_probe,
.priv_auto = sizeof(struct xilinx_pcie),
+ .probe = pcie_xilinx_probe,
};
--
2.34.1
More information about the U-Boot
mailing list