summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2018-08-01 10:38:29 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2018-08-08 09:28:04 +0200
commitdcad7abc47f78d401519e64a6d917a2835af26d5 (patch)
tree6e48bd204b25c053b8ea3e77e80b1b98226545c9
parent6d1b29be91570b2407b7e072260a4990073de9a7 (diff)
downloadbarebox-dcad7abc47f78d401519e64a6d917a2835af26d5.tar.gz
barebox-dcad7abc47f78d401519e64a6d917a2835af26d5.tar.xz
PCI: link PCI devices with potentially existing OF nodes
The document "PCI Bus Binding to: IEEE Std 1275-1994 Standard for Boot (Initialization Configuration) Firmware" describes how the PCI topology can be described in the DT, in order to augment the PCI devices with additional information via DT properties. This patch links OF nodes to the corresponding PCI devices if they exist, allowing PCI device drivers to query DT information like any platform device. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/pci/pci.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b2570eb15..bd8b7278e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -331,6 +331,31 @@ static void postscan_setup_bridge(struct pci_dev *dev)
}
}
+static struct device_node *
+pci_of_match_device(struct device_d *parent, unsigned int devfn)
+{
+ struct device_node *np;
+ u32 reg;
+
+ if (!IS_ENABLED(CONFIG_OFTREE) || !parent->device_node)
+ return NULL;
+
+ for_each_child_of_node(parent->device_node, np) {
+ if (!of_property_read_u32_array(np, "reg", &reg, 1)) {
+ /*
+ * Only match device/function pair of the device
+ * address, other properties are defined by the
+ * PCI/OF node topology.
+ */
+ reg = (reg >> 8) & 0xffff;
+ if (reg == devfn)
+ return np;
+ }
+ }
+
+ return NULL;
+}
+
unsigned int pci_scan_bus(struct pci_bus *bus)
{
struct pci_dev *dev;
@@ -368,6 +393,11 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
dev->vendor = l & 0xffff;
dev->device = (l >> 16) & 0xffff;
dev->dev.parent = bus->parent;
+ dev->dev.device_node = pci_of_match_device(bus->parent, devfn);
+ if (dev->dev.device_node)
+ pr_debug("found DT node %s for device %04x:%04x\n",
+ dev->dev.device_node->full_name,
+ dev->vendor, dev->device);
/* non-destructively determine if device can be a master: */
pci_read_config_byte(dev, PCI_COMMAND, &cmd);