diff options
author | Marek Vasut | 2018-10-10 21:27:06 +0200 |
---|---|---|
committer | Tom Rini | 2018-10-20 15:23:38 -0400 |
commit | 02e4d38d87cbc2778321e4d50cf805c6a7fb3f64 (patch) | |
tree | d1d1d0c46c040a89d4417f05397e15c2bc507483 | |
parent | 8a3d734b1b7b613f9fd1b66b2e66d19bff4bab9d (diff) |
pci: Support parsing PCI controller DT subnodes
The PCI controller can have DT subnodes describing extra properties
of particular PCI devices, ie. a PHY attached to an EHCI controller
on a PCI bus. This patch parses those DT subnodes and assigns a node
to the PCI device instance, so that the driver can extract details
from that node and ie. configure the PHY using the PHY subsystem.
Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
-rw-r--r-- | drivers/pci/pci-uclass.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index eb118f3496e..da49c96ed5e 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -90,6 +90,27 @@ int pci_get_ff(enum pci_size_t size) } } +static void pci_dev_find_ofnode(struct udevice *bus, phys_addr_t bdf, + ofnode *rnode) +{ + struct fdt_pci_addr addr; + ofnode node; + int ret; + + dev_for_each_subnode(node, bus) { + ret = ofnode_read_pci_addr(node, FDT_PCI_SPACE_CONFIG, "reg", + &addr); + if (ret) + continue; + + if (PCI_MASK_BUS(addr.phys_hi) != PCI_MASK_BUS(bdf)) + continue; + + *rnode = node; + break; + } +}; + int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, struct udevice **devp) { @@ -641,6 +662,7 @@ static int pci_find_and_bind_driver(struct udevice *parent, pci_dev_t bdf, struct udevice **devp) { struct pci_driver_entry *start, *entry; + ofnode node = ofnode_null(); const char *drv; int n_ents; int ret; @@ -651,6 +673,10 @@ static int pci_find_and_bind_driver(struct udevice *parent, debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__, find_id->vendor, find_id->device); + + /* Determine optional OF node */ + pci_dev_find_ofnode(parent, bdf, &node); + start = ll_entry_start(struct pci_driver_entry, pci_driver_entry); n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry); for (entry = start; entry != start + n_ents; entry++) { @@ -684,8 +710,8 @@ static int pci_find_and_bind_driver(struct udevice *parent, * find another driver. For now this doesn't seem * necesssary, so just bind the first match. */ - ret = device_bind(parent, drv, drv->name, NULL, -1, - &dev); + ret = device_bind_ofnode(parent, drv, drv->name, NULL, + node, &dev); if (ret) goto error; debug("%s: Match found: %s\n", __func__, drv->name); @@ -712,7 +738,7 @@ static int pci_find_and_bind_driver(struct udevice *parent, return -ENOMEM; drv = bridge ? "pci_bridge_drv" : "pci_generic_drv"; - ret = device_bind_driver(parent, drv, str, devp); + ret = device_bind_driver_to_node(parent, drv, str, node, devp); if (ret) { debug("%s: Failed to bind generic driver: %d\n", __func__, ret); free(str); |