Merge tag 'for-linus' of git://github.com/openrisc/linux
[linux-2.6-microblaze.git] / drivers / of / device.c
index c5a9473..5b043ee 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/of_device.h>
 #include <linux/of_address.h>
 #include <linux/of_iommu.h>
+#include <linux/of_reserved_mem.h>
 #include <linux/dma-direct.h> /* for bus_dma_region */
 #include <linux/dma-map-ops.h>
 #include <linux/init.h>
@@ -52,6 +53,42 @@ int of_device_add(struct platform_device *ofdev)
        return device_add(&ofdev->dev);
 }
 
+static void
+of_dma_set_restricted_buffer(struct device *dev, struct device_node *np)
+{
+       struct device_node *node, *of_node = dev->of_node;
+       int count, i;
+
+       if (!IS_ENABLED(CONFIG_DMA_RESTRICTED_POOL))
+               return;
+
+       count = of_property_count_elems_of_size(of_node, "memory-region",
+                                               sizeof(u32));
+       /*
+        * If dev->of_node doesn't exist or doesn't contain memory-region, try
+        * the OF node having DMA configuration.
+        */
+       if (count <= 0) {
+               of_node = np;
+               count = of_property_count_elems_of_size(
+                       of_node, "memory-region", sizeof(u32));
+       }
+
+       for (i = 0; i < count; i++) {
+               node = of_parse_phandle(of_node, "memory-region", i);
+               /*
+                * There might be multiple memory regions, but only one
+                * restricted-dma-pool region is allowed.
+                */
+               if (of_device_is_compatible(node, "restricted-dma-pool") &&
+                   of_device_is_available(node))
+                       break;
+       }
+
+       if (i != count && of_reserved_mem_device_init_by_idx(dev, of_node, i))
+               dev_warn(dev, "failed to initialise \"restricted-dma-pool\" memory node\n");
+}
+
 /**
  * of_dma_configure_id - Setup DMA configuration
  * @dev:       Device to apply DMA configuration
@@ -165,6 +202,9 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 
        arch_setup_dma_ops(dev, dma_start, size, iommu, coherent);
 
+       if (!iommu)
+               of_dma_set_restricted_buffer(dev, np);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(of_dma_configure_id);