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>
This commit is contained in:
parent
8a3d734b1b
commit
02e4d38d87
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user