]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/platforms/cell/iommu.c
[POWERPC] Cell fixup DMA offset for new southbridge
[karo-tx-linux.git] / arch / powerpc / platforms / cell / iommu.c
index a49ceb799a8efab4b4ecf5c74f0d9c67046ab1c8..e3ea5311476ed99925436b0ad4afd6e2db0d2848 100644 (file)
@@ -46,6 +46,8 @@
 
 #include "iommu.h"
 
+static dma_addr_t cell_dma_valid = SPIDER_DMA_VALID;
+
 static inline unsigned long 
 get_iopt_entry(unsigned long real_address, unsigned long ioid,
                         unsigned long prot)
@@ -255,9 +257,6 @@ static void enable_mapping(void __iomem *base, void __iomem *mmio_base)
        set_iost_origin(mmio_base);
 }
 
-static void iommu_dev_setup_null(struct pci_dev *d) { }
-static void iommu_bus_setup_null(struct pci_bus *b) { }
-
 struct cell_iommu {
        unsigned long base;
        unsigned long mmio_base;
@@ -306,17 +305,21 @@ static void cell_do_map_iommu(struct cell_iommu *iommu,
        }
 }
 
-static void iommu_devnode_setup(struct device_node *d)
+static void pci_dma_cell_bus_setup(struct pci_bus *b)
 {
-       unsigned int *ioid;
-       unsigned long *dma_window, map_start, map_size, token;
+       const unsigned int *ioid;
+       unsigned long map_start, map_size, token;
+       const unsigned long *dma_window;
        struct cell_iommu *iommu;
+       struct device_node *d;
+
+       d = pci_bus_to_OF_node(b);
 
-       ioid = (unsigned int *)get_property(d, "ioid", NULL);
+       ioid = get_property(d, "ioid", NULL);
        if (!ioid)
                pr_debug("No ioid entry found !\n");
 
-       dma_window = (unsigned long *)get_property(d, "ibm,dma-window", NULL);
+       dma_window = get_property(d, "ibm,dma-window", NULL);
        if (!dma_window)
                pr_debug("No ibm,dma-window entry found !\n");
 
@@ -329,12 +332,6 @@ static void iommu_devnode_setup(struct device_node *d)
        cell_do_map_iommu(iommu, *ioid, map_start, map_size);
 }
 
-static void iommu_bus_setup(struct pci_bus *b)
-{
-       struct device_node *d = (struct device_node *)b->sysdata;
-       iommu_devnode_setup(d);
-}
-
 
 static int cell_map_iommu_hardcoded(int num_nodes)
 {
@@ -344,8 +341,8 @@ static int cell_map_iommu_hardcoded(int num_nodes)
 
        /* node 0 */
        iommu = &cell_iommus[0];
-       iommu->mapped_base = ioremap(0x20000511000, 0x1000);
-       iommu->mapped_mmio_base = ioremap(0x20000510000, 0x1000);
+       iommu->mapped_base = ioremap(0x20000511000ul, 0x1000);
+       iommu->mapped_mmio_base = ioremap(0x20000510000ul, 0x1000);
 
        enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
 
@@ -357,8 +354,8 @@ static int cell_map_iommu_hardcoded(int num_nodes)
 
        /* node 1 */
        iommu = &cell_iommus[1];
-       iommu->mapped_base = ioremap(0x30000511000, 0x1000);
-       iommu->mapped_mmio_base = ioremap(0x30000510000, 0x1000);
+       iommu->mapped_base = ioremap(0x30000511000ul, 0x1000);
+       iommu->mapped_mmio_base = ioremap(0x30000510000ul, 0x1000);
 
        enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
 
@@ -371,8 +368,9 @@ static int cell_map_iommu_hardcoded(int num_nodes)
 
 static int cell_map_iommu(void)
 {
-       unsigned int num_nodes = 0, *node_id;
-       unsigned long *base, *mmio_base;
+       unsigned int num_nodes = 0;
+       const unsigned int *node_id;
+       const unsigned long *base, *mmio_base;
        struct device_node *dn;
        struct cell_iommu *iommu = NULL;
 
@@ -381,7 +379,7 @@ static int cell_map_iommu(void)
        for(dn = of_find_node_by_type(NULL, "cpu");
            dn;
            dn = of_find_node_by_type(dn, "cpu")) {
-               node_id = (unsigned int *)get_property(dn, "node-id", NULL);
+               node_id = get_property(dn, "node-id", NULL);
 
                if (num_nodes < *node_id)
                        num_nodes = *node_id;
@@ -396,9 +394,9 @@ static int cell_map_iommu(void)
            dn;
            dn = of_find_node_by_type(dn, "cpu")) {
 
-               node_id = (unsigned int *)get_property(dn, "node-id", NULL);
-               base = (unsigned long *)get_property(dn, "ioc-cache", NULL);
-               mmio_base = (unsigned long *)get_property(dn, "ioc-translation", NULL);
+               node_id = get_property(dn, "node-id", NULL);
+               base = get_property(dn, "ioc-cache", NULL);
+               mmio_base = get_property(dn, "ioc-translation", NULL);
 
                if (!base || !mmio_base || !node_id)
                        return cell_map_iommu_hardcoded(num_nodes);
@@ -427,7 +425,7 @@ static void *cell_alloc_coherent(struct device *hwdev, size_t size,
        ret = (void *)__get_free_pages(flag, get_order(size));
        if (ret != NULL) {
                memset(ret, 0, size);
-               *dma_handle = virt_to_abs(ret) | CELL_DMA_VALID;
+               *dma_handle = virt_to_abs(ret) | cell_dma_valid;
        }
        return ret;
 }
@@ -441,7 +439,7 @@ static void cell_free_coherent(struct device *hwdev, size_t size,
 static dma_addr_t cell_map_single(struct device *hwdev, void *ptr,
                size_t size, enum dma_data_direction direction)
 {
-       return virt_to_abs(ptr) | CELL_DMA_VALID;
+       return virt_to_abs(ptr) | cell_dma_valid;
 }
 
 static void cell_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
@@ -456,7 +454,7 @@ static int cell_map_sg(struct device *hwdev, struct scatterlist *sg,
 
        for (i = 0; i < nents; i++, sg++) {
                sg->dma_address = (page_to_phys(sg->page) + sg->offset)
-                                       | CELL_DMA_VALID;
+                                       | cell_dma_valid;
                sg->dma_length = sg->length;
        }
 
@@ -473,10 +471,26 @@ static int cell_dma_supported(struct device *dev, u64 mask)
        return mask < 0x100000000ull;
 }
 
+static struct dma_mapping_ops cell_iommu_ops = {
+       .alloc_coherent = cell_alloc_coherent,
+       .free_coherent = cell_free_coherent,
+       .map_single = cell_map_single,
+       .unmap_single = cell_unmap_single,
+       .map_sg = cell_map_sg,
+       .unmap_sg = cell_unmap_sg,
+       .dma_supported = cell_dma_supported,
+};
+
 void cell_init_iommu(void)
 {
        int setup_bus = 0;
 
+       /* If we have an Axon bridge, clear the DMA valid mask. This is fairly
+        * hackish but will work well enough until we have proper iommu code.
+        */
+       if (of_find_node_by_name(NULL, "axon"))
+               cell_dma_valid = 0;
+
        if (of_find_node_by_path("/mambo")) {
                pr_info("Not using iommu on systemsim\n");
        } else {
@@ -487,22 +501,13 @@ void cell_init_iommu(void)
 
                if (setup_bus) {
                        pr_debug("%s: IOMMU mapping activated\n", __FUNCTION__);
-                       ppc_md.iommu_dev_setup = iommu_dev_setup_null;
-                       ppc_md.iommu_bus_setup = iommu_bus_setup;
+                       ppc_md.pci_dma_bus_setup = pci_dma_cell_bus_setup;
                } else {
                        pr_debug("%s: IOMMU mapping activated, "
                                 "no device action necessary\n", __FUNCTION__);
                        /* Direct I/O, IOMMU off */
-                       ppc_md.iommu_dev_setup = iommu_dev_setup_null;
-                       ppc_md.iommu_bus_setup = iommu_bus_setup_null;
                }
        }
 
-       pci_dma_ops.alloc_coherent = cell_alloc_coherent;
-       pci_dma_ops.free_coherent = cell_free_coherent;
-       pci_dma_ops.map_single = cell_map_single;
-       pci_dma_ops.unmap_single = cell_unmap_single;
-       pci_dma_ops.map_sg = cell_map_sg;
-       pci_dma_ops.unmap_sg = cell_unmap_sg;
-       pci_dma_ops.dma_supported = cell_dma_supported;
+       pci_dma_ops = &cell_iommu_ops;
 }