Blame view

drivers/pci/of.c 2.15 KB
98d9f30c8   Benjamin Herrenschmidt   pci/of: Match PCI...
1
2
3
4
5
6
7
8
9
10
  /*
   * PCI <-> OF mapping helpers
   *
   * Copyright 2011 IBM Corp.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
   */
b165e2b60   Marc Zyngier   PCI/MSI: Add supp...
11
  #include <linux/irqdomain.h>
98d9f30c8   Benjamin Herrenschmidt   pci/of: Match PCI...
12
13
14
  #include <linux/kernel.h>
  #include <linux/pci.h>
  #include <linux/of.h>
c8d175883   Marc Zyngier   PCI/MSI: Use of_m...
15
  #include <linux/of_irq.h>
98d9f30c8   Benjamin Herrenschmidt   pci/of: Match PCI...
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  #include <linux/of_pci.h>
  #include "pci.h"
  
  void pci_set_of_node(struct pci_dev *dev)
  {
  	if (!dev->bus->dev.of_node)
  		return;
  	dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
  						    dev->devfn);
  }
  
  void pci_release_of_node(struct pci_dev *dev)
  {
  	of_node_put(dev->dev.of_node);
  	dev->dev.of_node = NULL;
  }
  
  void pci_set_bus_of_node(struct pci_bus *bus)
  {
  	if (bus->self == NULL)
  		bus->dev.of_node = pcibios_get_phb_of_node(bus);
  	else
  		bus->dev.of_node = of_node_get(bus->self->dev.of_node);
  }
  
  void pci_release_bus_of_node(struct pci_bus *bus)
  {
  	of_node_put(bus->dev.of_node);
  	bus->dev.of_node = NULL;
  }
  
  struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
  {
  	/* This should only be called for PHBs */
  	if (WARN_ON(bus->self || bus->parent))
  		return NULL;
  
  	/* Look for a node pointer in either the intermediary device we
  	 * create above the root bus or it's own parent. Normally only
  	 * the later is populated.
  	 */
  	if (bus->bridge->of_node)
  		return of_node_get(bus->bridge->of_node);
69566dd8b   David Daney   PCI: OF: Don't cr...
59
  	if (bus->bridge->parent && bus->bridge->parent->of_node)
98d9f30c8   Benjamin Herrenschmidt   pci/of: Match PCI...
60
61
62
  		return of_node_get(bus->bridge->parent->of_node);
  	return NULL;
  }
b165e2b60   Marc Zyngier   PCI/MSI: Add supp...
63
64
65
66
  
  struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)
  {
  #ifdef CONFIG_IRQ_DOMAIN
b165e2b60   Marc Zyngier   PCI/MSI: Add supp...
67
68
69
70
71
72
  	struct irq_domain *d;
  
  	if (!bus->dev.of_node)
  		return NULL;
  
  	/* Start looking for a phandle to an MSI controller. */
c8d175883   Marc Zyngier   PCI/MSI: Use of_m...
73
74
75
  	d = of_msi_get_domain(&bus->dev, bus->dev.of_node, DOMAIN_BUS_PCI_MSI);
  	if (d)
  		return d;
471c931cb   Marc Zyngier   PCI/MSI: Allow ms...
76
77
78
79
80
  
  	/*
  	 * If we don't have an msi-parent property, look for a domain
  	 * directly attached to the host bridge.
  	 */
c8d175883   Marc Zyngier   PCI/MSI: Use of_m...
81
  	d = irq_find_matching_host(bus->dev.of_node, DOMAIN_BUS_PCI_MSI);
b165e2b60   Marc Zyngier   PCI/MSI: Add supp...
82
83
  	if (d)
  		return d;
c8d175883   Marc Zyngier   PCI/MSI: Use of_m...
84
  	return irq_find_host(bus->dev.of_node);
b165e2b60   Marc Zyngier   PCI/MSI: Add supp...
85
86
87
88
  #else
  	return NULL;
  #endif
  }