Patrick Georgi has submitted this change. ( https://review.coreboot.org/c/coreboot/+/41384 )
Change subject: device/pci_device: Add notion of "hidden" PCI devices ......................................................................
device/pci_device: Add notion of "hidden" PCI devices
On some SoCs, there are PCI devices that may get hidden from PCI enumeration by platform firmware. Because the Vendor ID reads back as 0xffffffff, it appears that there is no PCI device located at that BDF. However, because the device does exist, designers may wish to hang its PCI resources off of a real __pci_driver, as well as have it participate in ACPI table generation.
This patch extends the semantics of the 'hidden' keyword in devicetree.cb. If a device now uses 'hidden' instead of 'on', then it will be assumed during PCI enumeration that the device indeed does exist, and it will not be removed as a "leftover device." This allows child devices to be enumerated correctly and also PCI resources can be designated from the {read,set}_resources callbacks.
It should be noted that as of this commit, there are precisely 0 devices using 'hidden' in their devicetree.cb files, so this should be a safe thing to do.
Later patches will begin moving PCI resources from random places (typically hung off of fixed SA and LPC) into the PMC device (procedure will vary per- platform).
Change-Id: I16c2d3e1d1433343e63dfc16856cff69cd815e2a Signed-off-by: Tim Wawrzynczak twawrzynczak@chromium.org Reviewed-on: https://review.coreboot.org/c/coreboot/+/41384 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Furquan Shaikh furquan@google.com --- M src/device/pci_device.c 1 file changed, 61 insertions(+), 2 deletions(-)
Approvals: build bot (Jenkins): Verified Furquan Shaikh: Looks good to me, approved
diff --git a/src/device/pci_device.c b/src/device/pci_device.c index 689325d..5f50a31 100644 --- a/src/device/pci_device.c +++ b/src/device/pci_device.c @@ -778,6 +778,13 @@ .reset_bus = pci_bus_reset, };
+/** Default device operations for PCI devices marked 'hidden' */ +static struct device_operations default_hidden_pci_ops_dev = { + .read_resources = noop_read_resources, + .set_resources = noop_set_resources, + .scan_bus = scan_static_bus, +}; + /** * Check for compatibility to route legacy VGA cycles through a bridge. * @@ -1147,6 +1154,46 @@ }
/** + * PCI devices that are marked as "hidden" do not get probed. However, the same + * initialization logic is still performed as if it were. This is useful when + * devices would like to be described in the devicetree.cb file, and/or present + * static PCI resources to the allocator, but the platform firmware hides the + * device (makes the device invisible to PCI enumeration) before PCI enumeration + * takes place. + * + * The expected semantics of PCI devices marked as 'hidden': + * 1) The device is actually present under the specified BDF + * 2) The device config space can still be accessed somehow, but the Vendor ID + * indicates there is no device there (it reads as 0xffffffff). + * 3) The device may still consume PCI resources. Typically, these would have + * been hardcoded elsewhere. + * + * @param dev Pointer to the device structure. + */ +static void pci_scan_hidden_device(struct device *dev) +{ + if (dev->chip_ops && dev->chip_ops->enable_dev) + dev->chip_ops->enable_dev(dev); + + /* + * If chip_ops->enable_dev did not set dev->ops, then set to a default + * .ops, because PCI enumeration is effectively being skipped, therefore + * no PCI driver will bind to this device. However, children may want to + * be enumerated, so this provides scan_static_bus for the .scan_bus + * callback. + */ + if (dev->ops == NULL) + dev->ops = &default_hidden_pci_ops_dev; + + if (dev->ops->enable) + dev->ops->enable(dev); + + /* Display the device almost as if it were probed normally */ + printk(BIOS_DEBUG, "%s [0000/%04x] hidden%s\n", dev_path(dev), + dev->device, dev->ops ? "" : " No operations"); +} + +/** * Scan a PCI bus. * * Determine the existence of devices and bridges on a PCI bus. If there are @@ -1190,6 +1237,14 @@ /* First thing setup the device structure. */ dev = pci_scan_get_dev(bus, devfn);
+ /* Devices marked 'hidden' do not get probed */ + if (dev && dev->hidden) { + pci_scan_hidden_device(dev); + + /* Skip pci_probe_dev, go to next devfn */ + continue; + } + /* See if a device is present and setup the device structure. */ dev = pci_probe_dev(dev, bus, devfn);
@@ -1213,8 +1268,12 @@
prev = &bus->children; for (dev = bus->children; dev; dev = dev->sibling) { - /* If we read valid vendor id, it is not leftover device. */ - if (dev->vendor != 0) { + /* + * The device is only considered leftover if it is not hidden + * and it has a Vendor ID of 0 (the default for a device that + * could not be probed). + */ + if (dev->vendor != 0 || dev->hidden) { prev = &dev->sibling; continue; }