pci: pcie_dw_common: introduce pcie_dw_find_capability()
authorNeil Armstrong <neil.armstrong@linaro.org>
Mon, 25 Nov 2024 09:46:16 +0000 (10:46 +0100)
committerCaleb Connolly <caleb.connolly@linaro.org>
Wed, 22 Jan 2025 15:43:53 +0000 (16:43 +0100)
Add PCIe config space capability search function specific for
the host controller, which are bridges *to* PCI devices but
are not PCI devices themselves.

Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://lore.kernel.org/r/20241125-topic-pcie-controller-v1-1-45c20070dd53@linaro.org
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
drivers/pci/pcie_dw_common.c
drivers/pci/pcie_dw_common.h

index 0673e51..7896127 100644 (file)
@@ -267,6 +267,48 @@ int pcie_dw_write_config(struct udevice *bus, pci_dev_t bdf,
                                                 pcie->io.bus_start, pcie->io.size);
 }
 
+/*
+ * These interfaces resemble the pci_find_*capability() interfaces, but these
+ * are for configuring host controllers, which are bridges *to* PCI devices but
+ * are not PCI devices themselves.
+ */
+static u8 pcie_dw_find_next_cap(struct pcie_dw *pci, u8 cap_ptr, u8 cap)
+{
+       u8 cap_id, next_cap_ptr;
+       u32 val;
+       u16 reg;
+
+       if (!cap_ptr)
+               return 0;
+
+       val = readl(pci->dbi_base + (cap_ptr & ~0x3));
+       reg = pci_conv_32_to_size(val, cap_ptr, 2);
+       cap_id = (reg & 0x00ff);
+
+       if (cap_id > PCI_CAP_ID_MAX)
+               return 0;
+
+       if (cap_id == cap)
+               return cap_ptr;
+
+       next_cap_ptr = (reg & 0xff00) >> 8;
+       return pcie_dw_find_next_cap(pci, next_cap_ptr, cap);
+}
+
+u8 pcie_dw_find_capability(struct pcie_dw *pci, u8 cap)
+{
+       u8 next_cap_ptr;
+       u32 val;
+       u16 reg;
+
+       val = readl(pci->dbi_base + (PCI_CAPABILITY_LIST & ~0x3));
+       reg = pci_conv_32_to_size(val, PCI_CAPABILITY_LIST, 2);
+
+       next_cap_ptr = (reg & 0x00ff);
+
+       return pcie_dw_find_next_cap(pci, next_cap_ptr, cap);
+}
+
 /**
  * pcie_dw_setup_host() - Setup the PCIe controller for RC opertaion
  *
index e0f7796..8cb99a1 100644 (file)
@@ -139,6 +139,8 @@ int pcie_dw_read_config(const struct udevice *bus, pci_dev_t bdf, uint offset, u
 int pcie_dw_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, ulong value,
                         enum pci_size_t size);
 
+u8 pcie_dw_find_capability(struct pcie_dw *pci, u8 cap);
+
 static inline void dw_pcie_dbi_write_enable(struct pcie_dw *pci, bool en)
 {
        u32 val;