This patch is an example how to use more than one IOMMU controller in a
device driver for hardware blocks, which have more then one dma master
(memory interface with iommu controller).

This patch is temporary, do not merge it yet.

Signed-off-by: Marek Szyprowski <m.szyprow...@samsung.com>
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 46 ++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 77b99ae..c2e95ab 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -22,7 +22,11 @@
 #include <media/v4l2-event.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <media/videobuf2-core.h>
+
+#include <asm/dma-iommu.h>
+
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_ctrl.h"
 #include "s5p_mfc_debug.h"
@@ -996,6 +1000,39 @@ static const struct v4l2_file_operations s5p_mfc_fops = {
        .mmap = s5p_mfc_mmap,
 };
 
+static struct device *s5p_mfc_alloc_memdev(struct device *dev, const char 
*name)
+{
+       struct device *child;
+       int ret;
+
+       child = devm_kzalloc(dev, sizeof(struct device), GFP_KERNEL);
+       if (!child)
+               return NULL;
+
+       device_initialize(child);
+       dev_set_name(child, "%s:%s", dev_name(dev), name);
+       child->parent = dev;
+       child->bus = dev->bus;
+       child->coherent_dma_mask = dev->coherent_dma_mask;
+       child->dma_mask = dev->dma_mask;
+
+       if (device_add(child) == 0) {
+               ret = arm_iommu_create_default_mapping(child, 0x20000000,
+                                                      SZ_256M);
+               if (ret == 0)
+                       return child;
+       }
+
+       put_device(child);
+       return NULL;
+}
+
+void s5p_mfc_free_memdev(struct device *dev)
+{
+       arm_iommu_release_default_mapping(dev);
+       put_device(dev);
+}
+
 static void *mfc_get_drv_data(struct platform_device *pdev);
 
 /* MFC probe function */
@@ -1049,8 +1086,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
                goto err_res;
        }
 
-       dev->mem_dev_l = &dev->plat_dev->dev;
-       dev->mem_dev_r = &dev->plat_dev->dev;
+       dev->mem_dev_l = s5p_mfc_alloc_memdev(&dev->plat_dev->dev, "left");
+       dev->mem_dev_r = s5p_mfc_alloc_memdev(&dev->plat_dev->dev, "right");
 
        dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
        if (IS_ERR(dev->alloc_ctx[0])) {
@@ -1181,6 +1218,10 @@ static int s5p_mfc_remove(struct platform_device *pdev)
        s5p_mfc_release_firmware(dev);
        vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
        vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
+       if (dev->mem_dev_l)
+               s5p_mfc_free_memdev(dev->mem_dev_l);
+       if (dev->mem_dev_r)
+               s5p_mfc_free_memdev(dev->mem_dev_r);
 
        s5p_mfc_final_pm(dev);
        return 0;
@@ -1436,6 +1477,7 @@ static struct platform_driver s5p_mfc_driver = {
                .owner  = THIS_MODULE,
                .pm     = &s5p_mfc_pm_ops,
                .of_match_table = exynos_mfc_match,
+               .flags  = DRIVER_HAS_OWN_IOMMU_MANAGER,
        },
 };
 
-- 
1.9.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to