From 96bb5c00f6a2b1d67c1f98c1c31ac9ca85e37b1a Mon Sep 17 00:00:00 2001 From: John Sheu Date: Wed, 6 Feb 2013 17:13:54 -0800 Subject: [PATCH] ARM: EXYNOS: MFC: Add IOMMU mapping to MFC probe 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 Reviewed-on: https://gerrit.chromium.org/gerrit/42958 Reviewed-by: Pawel Osciak Commit-Queue: John Sheu Tested-by: John Sheu --- drivers/media/video/s5p-mfc/s5p_mfc.c | 69 +++++++++++++++++++++------ 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c index 41b4ae6e66e0..acef5febc5c1 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c @@ -31,6 +31,10 @@ #include "s5p_mfc_opr.h" #include "s5p_mfc_cmd.h" #include "s5p_mfc_pm.h" +#ifdef CONFIG_EXYNOS_IOMMU +#include +#include +#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); -- 2.20.1