|
@@ -620,3 +620,72 @@ int fdt_resize(void *blob)
|
|
|
|
|
|
return actualsize;
|
|
|
}
|
|
|
+
|
|
|
+#ifdef CONFIG_PCI
|
|
|
+#define CONFIG_SYS_PCI_NR_INBOUND_WIN 3
|
|
|
+
|
|
|
+#define FDT_PCI_PREFETCH (0x40000000)
|
|
|
+#define FDT_PCI_MEM32 (0x02000000)
|
|
|
+#define FDT_PCI_IO (0x01000000)
|
|
|
+#define FDT_PCI_MEM64 (0x03000000)
|
|
|
+
|
|
|
+int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose) {
|
|
|
+
|
|
|
+ int addrcell, sizecell, len, r;
|
|
|
+ u32 *dma_range;
|
|
|
+ /* sized based on pci addr cells, size-cells, & address-cells */
|
|
|
+ u32 dma_ranges[(3 + 2 + 2) * CONFIG_SYS_PCI_NR_INBOUND_WIN];
|
|
|
+
|
|
|
+ addrcell = fdt_getprop_u32_default(blob, "/", "#address-cells", 1);
|
|
|
+ sizecell = fdt_getprop_u32_default(blob, "/", "#size-cells", 1);
|
|
|
+
|
|
|
+ dma_range = &dma_ranges[0];
|
|
|
+ for (r = 0; r < hose->region_count; r++) {
|
|
|
+ u64 bus_start, phys_start, size;
|
|
|
+
|
|
|
+ /* skip if !PCI_REGION_MEMORY */
|
|
|
+ if (!(hose->regions[r].flags & PCI_REGION_MEMORY))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ bus_start = (u64)hose->regions[r].bus_start;
|
|
|
+ phys_start = (u64)hose->regions[r].phys_start;
|
|
|
+ size = (u64)hose->regions[r].size;
|
|
|
+
|
|
|
+ dma_range[0] = 0;
|
|
|
+ if (size > 0x100000000ull)
|
|
|
+ dma_range[0] |= FDT_PCI_MEM64;
|
|
|
+ else
|
|
|
+ dma_range[0] |= FDT_PCI_MEM32;
|
|
|
+ if (hose->regions[r].flags & PCI_REGION_PREFETCH)
|
|
|
+ dma_range[0] |= FDT_PCI_PREFETCH;
|
|
|
+#ifdef CONFIG_SYS_PCI_64BIT
|
|
|
+ dma_range[1] = bus_start >> 32;
|
|
|
+#else
|
|
|
+ dma_range[1] = 0;
|
|
|
+#endif
|
|
|
+ dma_range[2] = bus_start & 0xffffffff;
|
|
|
+
|
|
|
+ if (addrcell == 2) {
|
|
|
+ dma_range[3] = phys_start >> 32;
|
|
|
+ dma_range[4] = phys_start & 0xffffffff;
|
|
|
+ } else {
|
|
|
+ dma_range[3] = phys_start & 0xffffffff;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sizecell == 2) {
|
|
|
+ dma_range[3 + addrcell + 0] = size >> 32;
|
|
|
+ dma_range[3 + addrcell + 1] = size & 0xffffffff;
|
|
|
+ } else {
|
|
|
+ dma_range[3 + addrcell + 0] = size & 0xffffffff;
|
|
|
+ }
|
|
|
+
|
|
|
+ dma_range += (3 + addrcell + sizecell);
|
|
|
+ }
|
|
|
+
|
|
|
+ len = dma_range - &dma_ranges[0];
|
|
|
+ if (len)
|
|
|
+ fdt_setprop(blob, phb_off, "dma-ranges", &dma_ranges[0], len*4);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|