diff options
-rw-r--r-- | drivers/pci/pci-uclass.c | 60 | ||||
-rw-r--r-- | include/pci.h | 25 |
2 files changed, 85 insertions, 0 deletions
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index b79927e..ad65427 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -775,6 +775,66 @@ static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); } +static int skip_to_next_device(struct udevice *bus, struct udevice **devp) +{ + struct udevice *dev; + int ret = 0; + + /* + * Scan through all the PCI controllers. On x86 there will only be one + * but that is not necessarily true on other hardware. + */ + do { + device_find_first_child(bus, &dev); + if (dev) { + *devp = dev; + return 0; + } + ret = uclass_next_device(&bus); + if (ret) + return ret; + } while (bus); + + return 0; +} + +int pci_find_next_device(struct udevice **devp) +{ + struct udevice *child = *devp; + struct udevice *bus = child->parent; + int ret; + + /* First try all the siblings */ + *devp = NULL; + while (child) { + device_find_next_child(&child); + if (child) { + *devp = child; + return 0; + } + } + + /* We ran out of siblings. Try the next bus */ + ret = uclass_next_device(&bus); + if (ret) + return ret; + + return bus ? skip_to_next_device(bus, devp) : 0; +} + +int pci_find_first_device(struct udevice **devp) +{ + struct udevice *bus; + int ret; + + *devp = NULL; + ret = uclass_first_device(UCLASS_PCI, &bus); + if (ret) + return ret; + + return skip_to_next_device(bus, devp); +} + UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", diff --git a/include/pci.h b/include/pci.h index d1e2765..488ff44 100644 --- a/include/pci.h +++ b/include/pci.h @@ -910,6 +910,31 @@ int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, struct udevice **devp); /** + * pci_find_first_device() - return the first available PCI device + * + * This function and pci_find_first_device() allow iteration through all + * available PCI devices on all buses. Assuming there are any, this will + * return the first one. + * + * @devp: Set to the first available device, or NULL if no more are left + * or we got an error + * @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe) + */ +int pci_find_first_device(struct udevice **devp); + +/** + * pci_find_next_device() - return the next available PCI device + * + * Finds the next available PCI device after the one supplied, or sets @devp + * to NULL if there are no more. + * + * @devp: On entry, the last device returned. Set to the next available + * device, or NULL if no more are left or we got an error + * @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe) + */ +int pci_find_next_device(struct udevice **devp); + +/** * pci_get_ff() - Returns a mask for the given access size * * @size: Access size |