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>
lime2-spi
Marek Vasut 6 years ago committed by Tom Rini
parent 8a3d734b1b
commit 02e4d38d87
  1. 32
      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, int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn,
struct udevice **devp) struct udevice **devp)
{ {
@ -641,6 +662,7 @@ static int pci_find_and_bind_driver(struct udevice *parent,
pci_dev_t bdf, struct udevice **devp) pci_dev_t bdf, struct udevice **devp)
{ {
struct pci_driver_entry *start, *entry; struct pci_driver_entry *start, *entry;
ofnode node = ofnode_null();
const char *drv; const char *drv;
int n_ents; int n_ents;
int ret; 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__, debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__,
find_id->vendor, find_id->device); 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); start = ll_entry_start(struct pci_driver_entry, pci_driver_entry);
n_ents = ll_entry_count(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++) { 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 * find another driver. For now this doesn't seem
* necesssary, so just bind the first match. * necesssary, so just bind the first match.
*/ */
ret = device_bind(parent, drv, drv->name, NULL, -1, ret = device_bind_ofnode(parent, drv, drv->name, NULL,
&dev); node, &dev);
if (ret) if (ret)
goto error; goto error;
debug("%s: Match found: %s\n", __func__, drv->name); 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; return -ENOMEM;
drv = bridge ? "pci_bridge_drv" : "pci_generic_drv"; 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) { if (ret) {
debug("%s: Failed to bind generic driver: %d\n", __func__, ret); debug("%s: Failed to bind generic driver: %d\n", __func__, ret);
free(str); free(str);

Loading…
Cancel
Save