Linux Audio

Check our new training course

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