Get the memory ranges for the PCIe from the FDT and add them to the MMU. This is necessary so that the PCIe driver in libbsd can work. --- bsps/powerpc/qoriq/start/mmu-config.c | 88 +++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)
diff --git a/bsps/powerpc/qoriq/start/mmu-config.c b/bsps/powerpc/qoriq/start/mmu-config.c index 58b08c8349..15e4a83fc4 100644 --- a/bsps/powerpc/qoriq/start/mmu-config.c +++ b/bsps/powerpc/qoriq/start/mmu-config.c @@ -305,6 +305,92 @@ static void TEXT config_fdt_adjust(const void *fdt) } } +/* + * Each PCIe controller has a ranges attribute in the fdt like the following: + * + * ranges = <0x2000000 0x00 0xc0000000 0x00 0xc0000000 0x00 0x20000000 + * 0x1000000 0x00 0x00000000 0x00 0xffc20000 0x00 0x00010000>; + * |------PCI address------| |-CPU address-| |-----size----| + * + * In theory, some fdt-attributes should be used to find out how long the PCI + * address (#address-cells of the PCIe node), the CPU address (#address-cells of + * the parent node) and the size (#size-cells of the PCIe node) are. In our case + * the structure is fixed because the pcie root controllers are a part of the + * chip. Therefore the sizes will never change and we can assume fixed lengths. + * + * The first cell of the PCI address holds a number of flags. A detailed + * explanation can be found for example here: + * + * https://web.archive.org/web/20240109080338/https://michael2012z.medium.com/understanding-pci-node-in-fdt-769a894a13cc + * + * We are only interested in the entry with the flags 0x02000000 which basically + * means that it is a non-relocatable, non-prefetchable, not-aliased 32 bit + * memory space on the first bus. + * + * The other two cells of the PCI address are a 64 Bit address viewed from PCI + * address space. The two CPU address cells are the same 64 Bit address viewed + * from CPU address space. For our controller these two should always be the + * same (no address translation). The last two cells give a size of the memory + * region (in theory in PCI address space but it has to be the same for CPU and + * PCI). + */ +static void TEXT add_pcie_regions(qoriq_mmu_context *context, const void *fdt) +{ + int node; + + node = -1; + + while (true) { + static const size_t range_length = 7 * 4; + const void *val; + int len; + + node = fdt_node_offset_by_compatible( + fdt, + node, + "fsl,mpc8548-pcie" + ); + if (node < 0) { + break; + } + + val = fdt_getprop(fdt, node, "ranges", &len); + if (len % range_length != 0) { + continue; + } + + while (len >= range_length) { + uint32_t pci_addr_flags; + uintptr_t pci_addr; + uintptr_t cpu_addr; + uintptr_t size; + const uint32_t *cells; + + cells = val; + pci_addr_flags = fdt32_to_cpu(cells[0]); + pci_addr = fdt64_to_cpu(*(fdt64_t *)(&cells[1])); + cpu_addr = fdt64_to_cpu(*(fdt64_t *)(&cells[3])); + size = fdt64_to_cpu(*(fdt64_t *)(&cells[5])); + + if (pci_addr_flags == 0x02000000 && + pci_addr == cpu_addr) { + /* Add as I/O memory */ + qoriq_mmu_add( + context, + cpu_addr, + cpu_addr + size - 1, + 0, + FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, + 0 + ); + } + len -= range_length; + val += range_length; + } + } +} + void TEXT qoriq_mmu_config(bool boot_processor, int first_tlb, int scratch_tlb) { qoriq_mmu_context context; @@ -349,6 +435,8 @@ void TEXT qoriq_mmu_config(bool boot_processor, int first_tlb, int scratch_tlb) } } + add_pcie_regions(&context, fdt); + qoriq_mmu_partition(&context, max_count); qoriq_mmu_write_to_tlb1(&context, first_tlb); } -- 2.35.3 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel