The diff below fixes an issue with using the rpi4 with newer
RaspberryPi firmware in combination with the EDK2-based UEFI firmware.
The problem is that the EDK2-based firmware programs the outbound mmio
window in a way that is incompatible with the device tree.  There are
multiple ways to fix this, but the diff below simply reprograms the
window with the values from the device tree.

ok?


Index: dev/fdt/bcm2711_pcie.c
===================================================================
RCS file: /cvs/src/sys/dev/fdt/bcm2711_pcie.c,v
retrieving revision 1.3
diff -u -p -r1.3 bcm2711_pcie.c
--- dev/fdt/bcm2711_pcie.c      14 Jul 2020 15:42:19 -0000      1.3
+++ dev/fdt/bcm2711_pcie.c      17 Jan 2021 18:02:09 -0000
@@ -28,12 +28,18 @@
 #include <dev/pci/pcidevs.h>
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
+#include <dev/pci/ppbreg.h>
 
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/fdt.h>
 
-#define PCIE_EXT_CFG_DATA      0x8000
-#define PCIE_EXT_CFG_INDEX     0x9000
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO               0x400c
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI               0x4010
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT       0x4070
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI          0x4080
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI         0x4084
+#define PCIE_EXT_CFG_DATA                              0x8000
+#define PCIE_EXT_CFG_INDEX                             0x9000
 
 #define HREAD4(sc, reg)                                                        
\
        (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
@@ -174,6 +180,31 @@ bcmpcie_attach(struct device *parent, st
        }
 
        free(ranges, M_TEMP, rangeslen);
+
+       /*
+        * Reprogram the outbound window to match the configuration in
+        * the device tree.  This is necessary since the EDK2-based
+        * UEFI firmware reprograms the window.
+        */
+       for (i = 0; i < sc->sc_nranges; i++) {
+               if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000) {
+                       uint64_t cpu_base = sc->sc_ranges[i].phys_base;
+                       uint64_t cpu_limit = sc->sc_ranges[i].phys_base +
+                           sc->sc_ranges[i].size - 1;
+
+                       HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO,
+                           sc->sc_ranges[i].pci_base);
+                       HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI,
+                           sc->sc_ranges[i].pci_base >> 32);
+                       HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
+                           (cpu_base & PPB_MEM_MASK) >> PPB_MEM_SHIFT |
+                           (cpu_limit & PPB_MEM_MASK));
+                       HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI,
+                           cpu_base >> 32);
+                       HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI,
+                           cpu_limit >> 32);
+               }
+       }
 
        printf("\n");
 

Reply via email to