[PATCH 03/11] pci: xilinx: Add probe function and improve memory region handling

Michal Simek monstr at monstr.eu
Tue Jun 3 18:06:38 CEST 2025



On 6/3/25 15:39, Uros Stajic wrote:
> 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,
>   };

NACK. Defining second probe to overwrite original one is definitely not a good 
approach.

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP/Versal ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal/Versal NET SoCs
TF-A maintainer - Xilinx ZynqMP/Versal/Versal NET SoCs



More information about the U-Boot mailing list