summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/device/pciexp_device.c32
-rw-r--r--src/include/device/pciexp.h2
2 files changed, 23 insertions, 11 deletions
diff --git a/src/device/pciexp_device.c b/src/device/pciexp_device.c
index e0b3544874..c52530196d 100644
--- a/src/device/pciexp_device.c
+++ b/src/device/pciexp_device.c
@@ -8,29 +8,39 @@
#include <device/pci_ops.h>
#include <device/pciexp.h>
-unsigned int pciexp_find_extended_cap(const struct device *dev, unsigned int cap)
+static unsigned int pciexp_get_ext_cap_offset(const struct device *dev, unsigned int cap,
+ unsigned int offset)
{
- unsigned int this_cap_offset, next_cap_offset;
- unsigned int this_cap, cafe;
-
- this_cap_offset = PCIE_EXT_CAP_OFFSET;
+ unsigned int this_cap_offset = offset;
+ unsigned int next_cap_offset, this_cap, cafe;
do {
this_cap = pci_read_config32(dev, this_cap_offset);
- next_cap_offset = this_cap >> 20;
- this_cap &= 0xffff;
cafe = pci_read_config32(dev, this_cap_offset + 4);
- cafe &= 0xffff;
- if (this_cap == cap)
+ if ((this_cap & 0xffff) == cap) {
return this_cap_offset;
- else if (cafe == cap)
+ } else if ((cafe & 0xffff) == cap) {
return this_cap_offset + 4;
- else
+ } else {
+ next_cap_offset = this_cap >> 20;
this_cap_offset = next_cap_offset;
+ }
} while (next_cap_offset != 0);
return 0;
}
+unsigned int pciexp_find_next_extended_cap(const struct device *dev, unsigned int cap,
+ unsigned int pos)
+{
+ const unsigned int next_cap_offset = pci_read_config32(dev, pos) >> 20;
+ return pciexp_get_ext_cap_offset(dev, cap, next_cap_offset);
+}
+
+unsigned int pciexp_find_extended_cap(const struct device *dev, unsigned int cap)
+{
+ return pciexp_get_ext_cap_offset(dev, cap, PCIE_EXT_CAP_OFFSET);
+}
+
/*
* Re-train a PCIe link
*/
diff --git a/src/include/device/pciexp.h b/src/include/device/pciexp.h
index a72c2ec2a9..30c2a54620 100644
--- a/src/include/device/pciexp.h
+++ b/src/include/device/pciexp.h
@@ -31,6 +31,8 @@ void pciexp_hotplug_scan_bridge(struct device *dev);
extern struct device_operations default_pciexp_hotplug_ops_bus;
unsigned int pciexp_find_extended_cap(const struct device *dev, unsigned int cap);
+unsigned int pciexp_find_next_extended_cap(const struct device *dev, unsigned int cap,
+ unsigned int offset);
static inline bool pciexp_is_downstream_port(int type)
{