summaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorBin Meng <bmeng.cn@gmail.com>2015-08-20 06:40:17 -0700
committerSimon Glass <sjg@chromium.org>2015-08-26 07:54:11 -0700
commit08fc7b8fac1d27d7e9f964309cbc32de0abd2c0d (patch)
treedfe0be588168641e42143b51b0373706368eb530 /drivers/pci
parentf86f0c1897436e03b0e68874a56b257080d01386 (diff)
downloadblackbird-obmc-uboot-08fc7b8fac1d27d7e9f964309cbc32de0abd2c0d.tar.gz
blackbird-obmc-uboot-08fc7b8fac1d27d7e9f964309cbc32de0abd2c0d.zip
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>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci-uclass.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 7d41d56fd4..416027438f 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -461,6 +461,7 @@ static int pci_find_and_bind_driver(struct udevice *parent,
int n_ents;
int ret;
char name[30], *str;
+ bool bridge;
*devp = NULL;
@@ -480,6 +481,17 @@ static int pci_find_and_bind_driver(struct udevice *parent,
continue;
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
* 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 */
sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf),
PCI_FUNC(bdf));
str = strdup(name);
if (!str)
return -ENOMEM;
- drv = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI ? "pci_bridge_drv" :
- "pci_generic_drv";
+ drv = bridge ? "pci_bridge_drv" : "pci_generic_drv";
+
ret = device_bind_driver(parent, drv, str, devp);
if (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;
/* Update the platform data */
- pplat = dev_get_parent_platdata(dev);
- pplat->devfn = PCI_MASK_BUS(bdf);
- pplat->vendor = vendor;
- pplat->device = device;
- pplat->class = class;
+ if (dev) {
+ pplat = dev_get_parent_platdata(dev);
+ pplat->devfn = PCI_MASK_BUS(bdf);
+ pplat->vendor = vendor;
+ pplat->device = device;
+ pplat->class = class;
+ }
}
return 0;
@@ -717,10 +740,6 @@ static int pci_uclass_post_probe(struct udevice *bus)
{
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);
ret = pci_bind_bus_devices(bus);
if (ret)
OpenPOWER on IntegriCloud