On Mon, Aug 10, 2015 at 9:05 PM, Simon Glass <s...@chromium.org> wrote: > 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 <s...@chromium.org> > --- > > Changes in v3: > - Drop the inner while() loop in skip_to_next_device() - it isn't needed > > Changes in v2: > - Add a comment as to why we need to scan multiple PCI controllers > > drivers/pci/pci-uclass.c | 60 > ++++++++++++++++++++++++++++++++++++++++++++++++ > include/pci.h | 25 ++++++++++++++++++++ > 2 files changed, 85 insertions(+) > > 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 > --
Reviewed-by: Bin Meng <bmeng...@gmail.com> _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot