[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