aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/of/Kconfig8
-rw-r--r--drivers/of/Makefile1
-rw-r--r--drivers/of/of_pci.c112
-rw-r--r--drivers/of/of_pci_irq.c92
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c2
-rw-r--r--drivers/pci/of.c61
-rw-r--r--drivers/pci/probe.c7
8 files changed, 200 insertions, 85 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index d06a6374ed6c..cac63c9f49ae 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -71,8 +71,14 @@ config OF_MDIO
71 71
72config OF_PCI 72config OF_PCI
73 def_tristate PCI 73 def_tristate PCI
74 depends on PCI && (PPC || MICROBLAZE || X86) 74 depends on PCI
75 help 75 help
76 OpenFirmware PCI bus accessors 76 OpenFirmware PCI bus accessors
77 77
78config OF_PCI_IRQ
79 def_tristate PCI
80 depends on OF_PCI && OF_IRQ
81 help
82 OpenFirmware PCI IRQ routing helpers
83
78endmenu # OF 84endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index f7861ed2f287..dccb1176be57 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_OF_NET) += of_net.o
10obj-$(CONFIG_OF_SPI) += of_spi.o 10obj-$(CONFIG_OF_SPI) += of_spi.o
11obj-$(CONFIG_OF_MDIO) += of_mdio.o 11obj-$(CONFIG_OF_MDIO) += of_mdio.o
12obj-$(CONFIG_OF_PCI) += of_pci.o 12obj-$(CONFIG_OF_PCI) += of_pci.o
13obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index ac1ec54e4fd5..ec7b060ae952 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -1,92 +1,40 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include <linux/of_pci.h> 2#include <linux/of_pci.h>
3#include <linux/of_irq.h>
4#include <asm/prom.h> 3#include <asm/prom.h>
5 4
6/** 5static inline int __of_pci_pci_compare(struct device_node *node,
7 * of_irq_map_pci - Resolve the interrupt for a PCI device 6 unsigned int devfn)
8 * @pdev: the device whose interrupt is to be resolved
9 * @out_irq: structure of_irq filled by this function
10 *
11 * This function resolves the PCI interrupt for a given PCI device. If a
12 * device-node exists for a given pci_dev, it will use normal OF tree
13 * walking. If not, it will implement standard swizzling and walk up the
14 * PCI tree until an device-node is found, at which point it will finish
15 * resolving using the OF tree walking.
16 */
17int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
18{ 7{
19 struct device_node *dn, *ppnode; 8 unsigned int size;
20 struct pci_dev *ppdev; 9 const __be32 *reg = of_get_property(node, "reg", &size);
21 u32 lspec;
22 __be32 lspec_be;
23 __be32 laddr[3];
24 u8 pin;
25 int rc;
26 10
27 /* Check if we have a device node, if yes, fallback to standard 11 if (!reg || size < 5 * sizeof(__be32))
28 * device tree parsing 12 return 0;
29 */ 13 return ((be32_to_cpup(&reg[0]) >> 8) & 0xff) == devfn;
30 dn = pci_device_to_OF_node(pdev); 14}
31 if (dn) {
32 rc = of_irq_map_one(dn, 0, out_irq);
33 if (!rc)
34 return rc;
35 }
36
37 /* Ok, we don't, time to have fun. Let's start by building up an
38 * interrupt spec. we assume #interrupt-cells is 1, which is standard
39 * for PCI. If you do different, then don't use that routine.
40 */
41 rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
42 if (rc != 0)
43 return rc;
44 /* No pin, exit */
45 if (pin == 0)
46 return -ENODEV;
47
48 /* Now we walk up the PCI tree */
49 lspec = pin;
50 for (;;) {
51 /* Get the pci_dev of our parent */
52 ppdev = pdev->bus->self;
53
54 /* Ouch, it's a host bridge... */
55 if (ppdev == NULL) {
56 ppnode = pci_bus_to_OF_node(pdev->bus);
57
58 /* No node for host bridge ? give up */
59 if (ppnode == NULL)
60 return -EINVAL;
61 } else {
62 /* We found a P2P bridge, check if it has a node */
63 ppnode = pci_device_to_OF_node(ppdev);
64 }
65
66 /* Ok, we have found a parent with a device-node, hand over to
67 * the OF parsing code.
68 * We build a unit address from the linux device to be used for
69 * resolution. Note that we use the linux bus number which may
70 * not match your firmware bus numbering.
71 * Fortunately, in most cases, interrupt-map-mask doesn't
72 * include the bus number as part of the matching.
73 * You should still be careful about that though if you intend
74 * to rely on this function (you ship a firmware that doesn't
75 * create device nodes for all PCI devices).
76 */
77 if (ppnode)
78 break;
79 15
80 /* We can only get here if we hit a P2P bridge with no node, 16struct device_node *of_pci_find_child_device(struct device_node *parent,
81 * let's do standard swizzling and try again 17 unsigned int devfn)
18{
19 struct device_node *node, *node2;
20
21 for_each_child_of_node(parent, node) {
22 if (__of_pci_pci_compare(node, devfn))
23 return node;
24 /*
25 * Some OFs create a parent node "multifunc-device" as
26 * a fake root for all functions of a multi-function
27 * device we go down them as well.
82 */ 28 */
83 lspec = pci_swizzle_interrupt_pin(pdev, lspec); 29 if (!strcmp(node->name, "multifunc-device")) {
84 pdev = ppdev; 30 for_each_child_of_node(node, node2) {
31 if (__of_pci_pci_compare(node2, devfn)) {
32 of_node_put(node);
33 return node2;
34 }
35 }
36 }
85 } 37 }
86 38 return NULL;
87 lspec_be = cpu_to_be32(lspec);
88 laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
89 laddr[1] = laddr[2] = cpu_to_be32(0);
90 return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
91} 39}
92EXPORT_SYMBOL_GPL(of_irq_map_pci); 40EXPORT_SYMBOL_GPL(of_pci_find_child_device);
diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
new file mode 100644
index 000000000000..ac1ec54e4fd5
--- /dev/null
+++ b/drivers/of/of_pci_irq.c
@@ -0,0 +1,92 @@
1#include <linux/kernel.h>
2#include <linux/of_pci.h>
3#include <linux/of_irq.h>
4#include <asm/prom.h>
5
6/**
7 * of_irq_map_pci - Resolve the interrupt for a PCI device
8 * @pdev: the device whose interrupt is to be resolved
9 * @out_irq: structure of_irq filled by this function
10 *
11 * This function resolves the PCI interrupt for a given PCI device. If a
12 * device-node exists for a given pci_dev, it will use normal OF tree
13 * walking. If not, it will implement standard swizzling and walk up the
14 * PCI tree until an device-node is found, at which point it will finish
15 * resolving using the OF tree walking.
16 */
17int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
18{
19 struct device_node *dn, *ppnode;
20 struct pci_dev *ppdev;
21 u32 lspec;
22 __be32 lspec_be;
23 __be32 laddr[3];
24 u8 pin;
25 int rc;
26
27 /* Check if we have a device node, if yes, fallback to standard
28 * device tree parsing
29 */
30 dn = pci_device_to_OF_node(pdev);
31 if (dn) {
32 rc = of_irq_map_one(dn, 0, out_irq);
33 if (!rc)
34 return rc;
35 }
36
37 /* Ok, we don't, time to have fun. Let's start by building up an
38 * interrupt spec. we assume #interrupt-cells is 1, which is standard
39 * for PCI. If you do different, then don't use that routine.
40 */
41 rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
42 if (rc != 0)
43 return rc;
44 /* No pin, exit */
45 if (pin == 0)
46 return -ENODEV;
47
48 /* Now we walk up the PCI tree */
49 lspec = pin;
50 for (;;) {
51 /* Get the pci_dev of our parent */
52 ppdev = pdev->bus->self;
53
54 /* Ouch, it's a host bridge... */
55 if (ppdev == NULL) {
56 ppnode = pci_bus_to_OF_node(pdev->bus);
57
58 /* No node for host bridge ? give up */
59 if (ppnode == NULL)
60 return -EINVAL;
61 } else {
62 /* We found a P2P bridge, check if it has a node */
63 ppnode = pci_device_to_OF_node(ppdev);
64 }
65
66 /* Ok, we have found a parent with a device-node, hand over to
67 * the OF parsing code.
68 * We build a unit address from the linux device to be used for
69 * resolution. Note that we use the linux bus number which may
70 * not match your firmware bus numbering.
71 * Fortunately, in most cases, interrupt-map-mask doesn't
72 * include the bus number as part of the matching.
73 * You should still be careful about that though if you intend
74 * to rely on this function (you ship a firmware that doesn't
75 * create device nodes for all PCI devices).
76 */
77 if (ppnode)
78 break;
79
80 /* We can only get here if we hit a P2P bridge with no node,
81 * let's do standard swizzling and try again
82 */
83 lspec = pci_swizzle_interrupt_pin(pdev, lspec);
84 pdev = ppdev;
85 }
86
87 lspec_be = cpu_to_be32(lspec);
88 laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
89 laddr[1] = laddr[2] = cpu_to_be32(0);
90 return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
91}
92EXPORT_SYMBOL_GPL(of_irq_map_pci);
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index c85f744270a5..f27f4a1488a1 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -70,4 +70,6 @@ obj-$(CONFIG_PCI_STUB) += pci-stub.o
70 70
71obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o 71obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
72 72
73obj-$(CONFIG_OF) += of.o
74
73ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG 75ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 083034710fa6..1d002b1c2bf4 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -158,7 +158,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
158 /* Scan below the new bridge */ 158 /* Scan below the new bridge */
159 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || 159 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
160 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) 160 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
161 of_scan_pci_bridge(dn, dev); 161 of_scan_pci_bridge(dev);
162 162
163 /* Map IO space for child bus, which may or may not succeed */ 163 /* Map IO space for child bus, which may or may not succeed */
164 pcibios_map_io_space(dev->subordinate); 164 pcibios_map_io_space(dev->subordinate);
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
new file mode 100644
index 000000000000..c94d37ec55c8
--- /dev/null
+++ b/drivers/pci/of.c
@@ -0,0 +1,61 @@
1/*
2 * PCI <-> OF mapping helpers
3 *
4 * Copyright 2011 IBM Corp.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/pci.h>
14#include <linux/of.h>
15#include <linux/of_pci.h>
16#include "pci.h"
17
18void pci_set_of_node(struct pci_dev *dev)
19{
20 if (!dev->bus->dev.of_node)
21 return;
22 dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
23 dev->devfn);
24}
25
26void pci_release_of_node(struct pci_dev *dev)
27{
28 of_node_put(dev->dev.of_node);
29 dev->dev.of_node = NULL;
30}
31
32void pci_set_bus_of_node(struct pci_bus *bus)
33{
34 if (bus->self == NULL)
35 bus->dev.of_node = pcibios_get_phb_of_node(bus);
36 else
37 bus->dev.of_node = of_node_get(bus->self->dev.of_node);
38}
39
40void pci_release_bus_of_node(struct pci_bus *bus)
41{
42 of_node_put(bus->dev.of_node);
43 bus->dev.of_node = NULL;
44}
45
46struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
47{
48 /* This should only be called for PHBs */
49 if (WARN_ON(bus->self || bus->parent))
50 return NULL;
51
52 /* Look for a node pointer in either the intermediary device we
53 * create above the root bus or it's own parent. Normally only
54 * the later is populated.
55 */
56 if (bus->bridge->of_node)
57 return of_node_get(bus->bridge->of_node);
58 if (bus->bridge->parent->of_node)
59 return of_node_get(bus->bridge->parent->of_node);
60 return NULL;
61}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 48849ffdd672..c28c7b91910e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -52,6 +52,7 @@ static void release_pcibus_dev(struct device *dev)
52 if (pci_bus->bridge) 52 if (pci_bus->bridge)
53 put_device(pci_bus->bridge); 53 put_device(pci_bus->bridge);
54 pci_bus_remove_resources(pci_bus); 54 pci_bus_remove_resources(pci_bus);
55 pci_release_bus_of_node(pci_bus);
55 kfree(pci_bus); 56 kfree(pci_bus);
56} 57}
57 58
@@ -588,7 +589,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
588 589
589 child->self = bridge; 590 child->self = bridge;
590 child->bridge = get_device(&bridge->dev); 591 child->bridge = get_device(&bridge->dev);
591 592 pci_set_bus_of_node(child);
592 pci_set_bus_speed(child); 593 pci_set_bus_speed(child);
593 594
594 /* Set up default resource pointers and names.. */ 595 /* Set up default resource pointers and names.. */
@@ -1038,6 +1039,7 @@ static void pci_release_dev(struct device *dev)
1038 1039
1039 pci_dev = to_pci_dev(dev); 1040 pci_dev = to_pci_dev(dev);
1040 pci_release_capabilities(pci_dev); 1041 pci_release_capabilities(pci_dev);
1042 pci_release_of_node(pci_dev);
1041 kfree(pci_dev); 1043 kfree(pci_dev);
1042} 1044}
1043 1045
@@ -1157,6 +1159,8 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
1157 dev->vendor = l & 0xffff; 1159 dev->vendor = l & 0xffff;
1158 dev->device = (l >> 16) & 0xffff; 1160 dev->device = (l >> 16) & 0xffff;
1159 1161
1162 pci_set_of_node(dev);
1163
1160 if (pci_setup_device(dev)) { 1164 if (pci_setup_device(dev)) {
1161 kfree(dev); 1165 kfree(dev);
1162 return NULL; 1166 return NULL;
@@ -1409,6 +1413,7 @@ struct pci_bus * pci_create_bus(struct device *parent,
1409 goto dev_reg_err; 1413 goto dev_reg_err;
1410 b->bridge = get_device(dev); 1414 b->bridge = get_device(dev);
1411 device_enable_async_suspend(b->bridge); 1415 device_enable_async_suspend(b->bridge);
1416 pci_set_bus_of_node(b);
1412 1417
1413 if (!parent) 1418 if (!parent)
1414 set_dev_node(b->bridge, pcibus_to_node(b)); 1419 set_dev_node(b->bridge, pcibus_to_node(b));