of_pci.c 1.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. #include <linux/kernel.h>
  2. #include <linux/export.h>
  3. #include <linux/of.h>
  4. #include <linux/of_pci.h>
  5. #include <asm/prom.h>
  6. static inline int __of_pci_pci_compare(struct device_node *node,
  7. unsigned int devfn)
  8. {
  9. unsigned int size;
  10. const __be32 *reg = of_get_property(node, "reg", &size);
  11. if (!reg || size < 5 * sizeof(__be32))
  12. return 0;
  13. return ((be32_to_cpup(&reg[0]) >> 8) & 0xff) == devfn;
  14. }
  15. struct device_node *of_pci_find_child_device(struct device_node *parent,
  16. unsigned int devfn)
  17. {
  18. struct device_node *node, *node2;
  19. for_each_child_of_node(parent, node) {
  20. if (__of_pci_pci_compare(node, devfn))
  21. return node;
  22. /*
  23. * Some OFs create a parent node "multifunc-device" as
  24. * a fake root for all functions of a multi-function
  25. * device we go down them as well.
  26. */
  27. if (!strcmp(node->name, "multifunc-device")) {
  28. for_each_child_of_node(node, node2) {
  29. if (__of_pci_pci_compare(node2, devfn)) {
  30. of_node_put(node);
  31. return node2;
  32. }
  33. }
  34. }
  35. }
  36. return NULL;
  37. }
  38. EXPORT_SYMBOL_GPL(of_pci_find_child_device);