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>
This commit is contained in:
parent
49be1a9346
commit
3d121ae1a1
|
@ -8,29 +8,39 @@
|
||||||
#include <device/pci_ops.h>
|
#include <device/pci_ops.h>
|
||||||
#include <device/pciexp.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_offset = offset;
|
||||||
unsigned int this_cap, cafe;
|
unsigned int next_cap_offset, this_cap, cafe;
|
||||||
|
|
||||||
this_cap_offset = PCIE_EXT_CAP_OFFSET;
|
|
||||||
do {
|
do {
|
||||||
this_cap = pci_read_config32(dev, this_cap_offset);
|
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 = pci_read_config32(dev, this_cap_offset + 4);
|
||||||
cafe &= 0xffff;
|
if ((this_cap & 0xffff) == cap) {
|
||||||
if (this_cap == cap)
|
|
||||||
return this_cap_offset;
|
return this_cap_offset;
|
||||||
else if (cafe == cap)
|
} else if ((cafe & 0xffff) == cap) {
|
||||||
return this_cap_offset + 4;
|
return this_cap_offset + 4;
|
||||||
else
|
} else {
|
||||||
|
next_cap_offset = this_cap >> 20;
|
||||||
this_cap_offset = next_cap_offset;
|
this_cap_offset = next_cap_offset;
|
||||||
|
}
|
||||||
} while (next_cap_offset != 0);
|
} while (next_cap_offset != 0);
|
||||||
|
|
||||||
return 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
|
* Re-train a PCIe link
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -31,6 +31,8 @@ void pciexp_hotplug_scan_bridge(struct device *dev);
|
||||||
extern struct device_operations default_pciexp_hotplug_ops_bus;
|
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_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)
|
static inline bool pciexp_is_downstream_port(int type)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue