ARM: EXYNOS: MFC: Add IOMMU mapping to MFC probe
authorJohn Sheu <sheu@chromium.org>
Thu, 7 Feb 2013 01:13:54 +0000 (17:13 -0800)
committerChromeBot <chrome-bot@google.com>
Sat, 2 Mar 2013 02:08:12 +0000 (18:08 -0800)
IOMMU mapping is created for mfc device during probe. This
requires the sysmmu_l and sysmmu_r property be set in the DTS
file. First, the sysmmu device nodes are found and then the
sysmmu platform devices are retrieved. A IOMMU mapping is then created
for mfc_l and mfc_r devices.

Change-Id: I270211bd2583492818d2f2eb2c9bac73ba3956cd
Signed-off-by: Prathyush K <prathyush.k@samsung.com>
Reviewed-on: https://gerrit.chromium.org/gerrit/42958
Reviewed-by: Pawel Osciak <posciak@chromium.org>
Commit-Queue: John Sheu <sheu@chromium.org>
Tested-by: John Sheu <sheu@chromium.org>
drivers/media/video/s5p-mfc/s5p_mfc.c

index 41b4ae6..acef5fe 100644 (file)
 #include "s5p_mfc_opr.h"
 #include "s5p_mfc_cmd.h"
 #include "s5p_mfc_pm.h"
+#ifdef CONFIG_EXYNOS_IOMMU
+#include <mach/sysmmu.h>
+#include <linux/of_platform.h>
+#endif
 
 #define S5P_MFC_NAME           "s5p-mfc"
 #define S5P_MFC_DEC_NAME       "s5p-mfc-dec"
@@ -991,12 +995,42 @@ static const struct v4l2_file_operations s5p_mfc_fops = {
        .mmap = s5p_mfc_mmap,
 };
 
-static int match_child(struct device *dev, void *data)
+#ifdef CONFIG_EXYNOS_IOMMU
+static int iommu_init(struct platform_device *pdev,
+                               struct device *mfc_l,
+                               struct device *mfc_r)
 {
-       if (!dev_name(dev))
-               return 0;
-       return !strcmp(dev_name(dev), (char *)data);
+       struct platform_device *pds;
+       struct dma_iommu_mapping *mapping;
+
+       pds = find_sysmmu_dt(pdev, "sysmmu_l");
+       if (pds == NULL) {
+               printk(KERN_ERR "no sysmmu_l found\n");
+               return -1;
+       }
+       platform_set_sysmmu(&pds->dev, mfc_l);
+       mapping = s5p_create_iommu_mapping(mfc_l, 0x20000000,
+                                               SZ_128M, 4, NULL);
+       if (mapping == NULL) {
+               printk(KERN_ERR "IOMMU mapping failed\n");
+               return -1;
+       }
+
+       pds = find_sysmmu_dt(pdev, "sysmmu_r");
+       if (pds == NULL) {
+               printk(KERN_ERR "no sysmmu_r found\n");
+               return -1;
+       }
+       platform_set_sysmmu(&pds->dev, mfc_r);
+       if (!s5p_create_iommu_mapping(mfc_r, 0x20000000,
+                                       SZ_128M, 4, mapping)) {
+               printk(KERN_ERR "IOMMU mapping failed\n");
+               return -1;
+       }
+
+       return 0;
 }
+#endif
 
 /* MFC probe function */
 static int s5p_mfc_probe(struct platform_device *pdev)
@@ -1052,22 +1086,28 @@ static int s5p_mfc_probe(struct platform_device *pdev)
                goto err_res;
        }
 
-       dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, "s5p-mfc-l",
-                                          match_child);
+       dev->mem_dev_l = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
        if (!dev->mem_dev_l) {
-               mfc_err("Mem child (L) device get failed\n");
-               ret = -ENODEV;
+               dev_err(&pdev->dev,
+                       "Not enough memory for MFC left memory bank device\n");
+               ret = -ENOMEM;
                goto err_res;
        }
-
-       dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r",
-                                          match_child);
+       dev->mem_dev_r = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
        if (!dev->mem_dev_r) {
-               mfc_err("Mem child (R) device get failed\n");
-               ret = -ENODEV;
+               dev_err(&pdev->dev,
+                       "Not enough memory for MFC right memory bank device\n");
+               ret = -ENOMEM;
                goto err_res;
        }
-
+#ifdef CONFIG_EXYNOS_IOMMU
+       dev->mem_dev_l->init_name = "mfc_l";
+       dev->mem_dev_r->init_name = "mfc_r";
+       if (iommu_init(pdev, dev->mem_dev_r, dev->mem_dev_l)) {
+               v4l2_err(&dev->v4l2_dev, "failed to initialize IOMMU\n");
+               goto err_iommu_init;
+       }
+#endif
        dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
        if (IS_ERR_OR_NULL(dev->alloc_ctx[0])) {
                ret = PTR_ERR(dev->alloc_ctx[0]);
@@ -1163,6 +1203,7 @@ err_v4l2_dev_reg:
        vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
 err_mem_init_ctx_1:
        vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
+err_iommu_init:
 err_res:
        s5p_mfc_final_pm(dev);