PCI: brcmstb: Wait for Raspberry Pi's firmware when present
authorNicolas Saenz Julienne <nsaenzjulienne@suse.de>
Tue, 5 May 2020 16:13:16 +0000 (18:13 +0200)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Wed, 13 May 2020 09:53:23 +0000 (10:53 +0100)
xHCI's PCI fixup, run at the end of pcie-brcmstb's probe, depends on
RPi4's VideoCore firmware interface to be up and running. It's possible
for both initializations to race, so make sure it's available prior to
starting.

Link: https://lore.kernel.org/r/20200505161318.26200-4-nsaenzjulienne@suse.de
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Rob Herring <robh@kernel.org>
drivers/pci/controller/pcie-brcmstb.c

index 752f5b3..7730ea8 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/string.h>
 #include <linux/types.h>
 
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
 #include "../pci.h"
 
 /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
@@ -929,11 +931,26 @@ static int brcm_pcie_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node, *msi_np;
        struct pci_host_bridge *bridge;
+       struct device_node *fw_np;
        struct brcm_pcie *pcie;
        struct pci_bus *child;
        struct resource *res;
        int ret;
 
+       /*
+        * We have to wait for Raspberry Pi's firmware interface to be up as a
+        * PCI fixup, rpi_firmware_init_vl805(), depends on it. This driver's
+        * probe can race with the firmware interface's (see
+        * drivers/firmware/raspberrypi.c) and potentially break the PCI fixup.
+        */
+       fw_np = of_find_compatible_node(NULL, NULL,
+                                       "raspberrypi,bcm2835-firmware");
+       if (fw_np && !rpi_firmware_get(fw_np)) {
+               of_node_put(fw_np);
+               return -EPROBE_DEFER;
+       }
+       of_node_put(fw_np);
+
        bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
        if (!bridge)
                return -ENOMEM;