linux/drivers/of/of_pci.c
<<
>>
Prefs
   1#include <linux/kernel.h>
   2#include <linux/export.h>
   3#include <linux/of.h>
   4#include <linux/of_pci.h>
   5
   6static inline int __of_pci_pci_compare(struct device_node *node,
   7                                       unsigned int data)
   8{
   9        int devfn;
  10
  11        devfn = of_pci_get_devfn(node);
  12        if (devfn < 0)
  13                return 0;
  14
  15        return devfn == data;
  16}
  17
  18struct device_node *of_pci_find_child_device(struct device_node *parent,
  19                                             unsigned int devfn)
  20{
  21        struct device_node *node, *node2;
  22
  23        for_each_child_of_node(parent, node) {
  24                if (__of_pci_pci_compare(node, devfn))
  25                        return node;
  26                /*
  27                 * Some OFs create a parent node "multifunc-device" as
  28                 * a fake root for all functions of a multi-function
  29                 * device we go down them as well.
  30                 */
  31                if (!strcmp(node->name, "multifunc-device")) {
  32                        for_each_child_of_node(node, node2) {
  33                                if (__of_pci_pci_compare(node2, devfn)) {
  34                                        of_node_put(node);
  35                                        return node2;
  36                                }
  37                        }
  38                }
  39        }
  40        return NULL;
  41}
  42EXPORT_SYMBOL_GPL(of_pci_find_child_device);
  43
  44/**
  45 * of_pci_get_devfn() - Get device and function numbers for a device node
  46 * @np: device node
  47 *
  48 * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
  49 * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
  50 * and function numbers respectively. On error a negative error code is
  51 * returned.
  52 */
  53int of_pci_get_devfn(struct device_node *np)
  54{
  55        unsigned int size;
  56        const __be32 *reg;
  57
  58        reg = of_get_property(np, "reg", &size);
  59
  60        if (!reg || size < 5 * sizeof(__be32))
  61                return -EINVAL;
  62
  63        return (be32_to_cpup(reg) >> 8) & 0xff;
  64}
  65EXPORT_SYMBOL_GPL(of_pci_get_devfn);
  66
  67/**
  68 * of_pci_parse_bus_range() - parse the bus-range property of a PCI device
  69 * @node: device node
  70 * @res: address to a struct resource to return the bus-range
  71 *
  72 * Returns 0 on success or a negative error-code on failure.
  73 */
  74int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
  75{
  76        const __be32 *values;
  77        int len;
  78
  79        values = of_get_property(node, "bus-range", &len);
  80        if (!values || len < sizeof(*values) * 2)
  81                return -EINVAL;
  82
  83        res->name = node->name;
  84        res->start = be32_to_cpup(values++);
  85        res->end = be32_to_cpup(values);
  86        res->flags = IORESOURCE_BUS;
  87
  88        return 0;
  89}
  90EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
  91
  92#ifdef CONFIG_PCI_MSI
  93
  94static LIST_HEAD(of_pci_msi_chip_list);
  95static DEFINE_MUTEX(of_pci_msi_chip_mutex);
  96
  97int of_pci_msi_chip_add(struct msi_controller *chip)
  98{
  99        if (!of_property_read_bool(chip->of_node, "msi-controller"))
 100                return -EINVAL;
 101
 102        mutex_lock(&of_pci_msi_chip_mutex);
 103        list_add(&chip->list, &of_pci_msi_chip_list);
 104        mutex_unlock(&of_pci_msi_chip_mutex);
 105
 106        return 0;
 107}
 108EXPORT_SYMBOL_GPL(of_pci_msi_chip_add);
 109
 110void of_pci_msi_chip_remove(struct msi_controller *chip)
 111{
 112        mutex_lock(&of_pci_msi_chip_mutex);
 113        list_del(&chip->list);
 114        mutex_unlock(&of_pci_msi_chip_mutex);
 115}
 116EXPORT_SYMBOL_GPL(of_pci_msi_chip_remove);
 117
 118struct msi_controller *of_pci_find_msi_chip_by_node(struct device_node *of_node)
 119{
 120        struct msi_controller *c;
 121
 122        mutex_lock(&of_pci_msi_chip_mutex);
 123        list_for_each_entry(c, &of_pci_msi_chip_list, list) {
 124                if (c->of_node == of_node) {
 125                        mutex_unlock(&of_pci_msi_chip_mutex);
 126                        return c;
 127                }
 128        }
 129        mutex_unlock(&of_pci_msi_chip_mutex);
 130
 131        return NULL;
 132}
 133EXPORT_SYMBOL_GPL(of_pci_find_msi_chip_by_node);
 134
 135#endif /* CONFIG_PCI_MSI */
 136