summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2015-08-10 07:05:04 -0600
committerSimon Glass <sjg@chromium.org>2015-08-14 03:24:21 -0600
commit76c3fbcd3db61b9a3d9c38b0c18968322c5b1588 (patch)
treef249db33f5aab55cca438a4eac045d96b6560d3d /drivers
parent66afb4ed924693412f2f4e05fbfae6a642159402 (diff)
downloadu-boot-imx-76c3fbcd3db61b9a3d9c38b0c18968322c5b1588.zip
u-boot-imx-76c3fbcd3db61b9a3d9c38b0c18968322c5b1588.tar.gz
u-boot-imx-76c3fbcd3db61b9a3d9c38b0c18968322c5b1588.tar.bz2
dm: pci: Add a way to iterate through all PCI devices
These functions allow iteration through all PCI devices including bridges. The children of each PCI bus are returned in turn. This can be useful for configuring, checking or enumerating all the devices. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/pci-uclass.c60
1 files changed, 60 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",