fdt: Added helper to set PCI dma-ranges property
authorKumar Gala <galak@kernel.crashing.org>
Thu, 23 Oct 2008 04:33:56 +0000 (23:33 -0500)
committerAndrew Fleming-AFLEMING <afleming@freescale.com>
Fri, 24 Oct 2008 22:34:57 +0000 (17:34 -0500)
Added fdt_pci_dma_ranges() that parses the pci_region info from the
struct pci_controller and populates the dma-ranges based on it.

The max # of windws/dma-ranges we support is 3 since on embedded
PowerPC based systems this is the max number of windows.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Andrew Fleming-AFLEMING <afleming@freescale.com>
common/fdt_support.c
include/fdt_support.h

index f4307774dc9da854fae649e96f42b6d76630fbe4..d483d66f11d2e8b7cb17d516927d72d4b9fd09eb 100644 (file)
@@ -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
index 816c9d08b90f211c5a6a34ab80feaf9110dbffc2..6062df9764271e50626db9621b3d9dd8cc524ac3 100644 (file)
@@ -65,6 +65,11 @@ void fdt_fixup_crypto_node(void *blob, int sec_rev);
 static inline void fdt_fixup_crypto_node(void *blob, int sec_rev) {}
 #endif
 
+#ifdef CONFIG_PCI
+#include <pci.h>
+int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose);
+#endif
+
 #ifdef CONFIG_OF_BOARD_SETUP
 void ft_board_setup(void *blob, bd_t *bd);
 void ft_cpu_setup(void *blob, bd_t *bd);