dm: pci: Support selected device/driver binding before relocation

On some platforms pci devices behind bridge need to be probed (eg:
a pci uart on recent x86 chipset) before relocation. But we won't
bind all devices found during the enumeration. Only devices whose
driver with DM_FLAG_PRE_RELOC set will be bound. Any other generic
devices except bridges won't be bound.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Bin Meng 2015-08-20 06:40:17 -07:00 committed by Simon Glass
parent f86f0c1897
commit 08fc7b8fac

View file

@ -461,6 +461,7 @@ static int pci_find_and_bind_driver(struct udevice *parent,
int n_ents; int n_ents;
int ret; int ret;
char name[30], *str; char name[30], *str;
bool bridge;
*devp = NULL; *devp = NULL;
@ -480,6 +481,17 @@ static int pci_find_and_bind_driver(struct udevice *parent,
continue; continue;
drv = entry->driver; drv = entry->driver;
/*
* In the pre-relocation phase, we only bind devices
* whose driver has the DM_FLAG_PRE_RELOC set, to save
* precious memory space as on some platforms as that
* space is pretty limited (ie: using Cache As RAM).
*/
if (!(gd->flags & GD_FLG_RELOC) &&
!(drv->flags & DM_FLAG_PRE_RELOC))
return 0;
/* /*
* We could pass the descriptor to the driver as * We could pass the descriptor to the driver as
* platdata (instead of NULL) and allow its bind() * platdata (instead of NULL) and allow its bind()
@ -499,14 +511,23 @@ static int pci_find_and_bind_driver(struct udevice *parent,
} }
} }
bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI;
/*
* In the pre-relocation phase, we only bind bridge devices to save
* precious memory space as on some platforms as that space is pretty
* limited (ie: using Cache As RAM).
*/
if (!(gd->flags & GD_FLG_RELOC) && !bridge)
return 0;
/* Bind a generic driver so that the device can be used */ /* Bind a generic driver so that the device can be used */
sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf), sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf),
PCI_FUNC(bdf)); PCI_FUNC(bdf));
str = strdup(name); str = strdup(name);
if (!str) if (!str)
return -ENOMEM; return -ENOMEM;
drv = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI ? "pci_bridge_drv" : drv = bridge ? "pci_bridge_drv" : "pci_generic_drv";
"pci_generic_drv";
ret = device_bind_driver(parent, drv, str, devp); ret = device_bind_driver(parent, drv, str, devp);
if (ret) { if (ret) {
debug("%s: Failed to bind generic driver: %d", __func__, ret); debug("%s: Failed to bind generic driver: %d", __func__, ret);
@ -589,11 +610,13 @@ int pci_bind_bus_devices(struct udevice *bus)
return ret; return ret;
/* Update the platform data */ /* Update the platform data */
pplat = dev_get_parent_platdata(dev); if (dev) {
pplat->devfn = PCI_MASK_BUS(bdf); pplat = dev_get_parent_platdata(dev);
pplat->vendor = vendor; pplat->devfn = PCI_MASK_BUS(bdf);
pplat->device = device; pplat->vendor = vendor;
pplat->class = class; pplat->device = device;
pplat->class = class;
}
} }
return 0; return 0;
@ -717,10 +740,6 @@ static int pci_uclass_post_probe(struct udevice *bus)
{ {
int ret; int ret;
/* Don't scan buses before relocation */
if (!(gd->flags & GD_FLG_RELOC))
return 0;
debug("%s: probing bus %d\n", __func__, bus->seq); debug("%s: probing bus %d\n", __func__, bus->seq);
ret = pci_bind_bus_devices(bus); ret = pci_bind_bus_devices(bus);
if (ret) if (ret)