summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/pci-uclass.c60
-rw-r--r--include/pci.h25
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