summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Wawrzynczak <twawrzynczak@chromium.org>2021-09-16 20:18:16 -0600
committerFelix Held <felix-coreboot@felixheld.de>2022-02-10 12:48:00 +0000
commit3d121ae1a16751d55006c9b907a283f03c639197 (patch)
tree9fd9479168b1eab48326024959a5dc192413c764
parent49be1a93467e6bd1bd61ec7889c0a6f24e824288 (diff)
device: Add pciexp_find_next_extended_cap function
Some PCIe devices have extended capability lists that contain multiples instances of the same capability. This patch provides a function similar to pciexp_find_extended_cap that can be used to search through multiple instances of the same capability by returning the offset of the next extended capability of the given type following the passed-in offset. The base functionality of searching for a given capability from an offset is extracted to a local helper function and both pciexp_find_extended_cap and pciexp_find_next_extended_cap use this helper. Change-Id: Ie68dc26012ba57650484c4f2ff53cc694a5347aa Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/57784 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Karthik Ramasubramanian <kramasub@google.com> Reviewed-by: Nick Vaccaro <nvaccaro@google.com>
-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)
{