of_pci.c 1.0 KB

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