diff mbox

[3/7] drm/exynos: add IOMMU support to drm fimd

Message ID 1341999603-28316-4-git-send-email-prathyush.k@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Prathyush K July 11, 2012, 9:39 a.m. UTC
This patch adds device tree based IOMMU support to DRM FIMD. During
probe, the driver searches for a 'sysmmu' field in the device node. The
sysmmu field points to the corresponding sysmmu device of fimd.
This sysmmu device is retrieved and set as fimd's sysmmu. The common
IOMMU mapping created during DRM init is then attached to drm fimd.

Signed-off-by: Prathyush K <prathyush.k@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c |   54 +++++++++++++++++++++++++++++-
 1 files changed, 53 insertions(+), 1 deletions(-)

Comments

Inki Dae July 13, 2012, 6:50 a.m. UTC | #1
> -----Original Message-----
> From: Prathyush K [mailto:prathyush.k@samsung.com]
> Sent: Wednesday, July 11, 2012 6:40 PM
> To: dri-devel@lists.freedesktop.org
> Cc: prathyush@chromium.org; m.szyprowski@samsung.com;
inki.dae@samsung.com;
> subash.ramaswamy@linaro.org
> Subject: [PATCH 3/7] drm/exynos: add IOMMU support to drm fimd
> 
> This patch adds device tree based IOMMU support to DRM FIMD. During
> probe, the driver searches for a 'sysmmu' field in the device node. The
> sysmmu field points to the corresponding sysmmu device of fimd.
> This sysmmu device is retrieved and set as fimd's sysmmu. The common
> IOMMU mapping created during DRM init is then attached to drm fimd.
> 
> Signed-off-by: Prathyush K <prathyush.k@samsung.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c |   54
> +++++++++++++++++++++++++++++-
>  1 files changed, 53 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index 15b5286..6d4048a 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -19,7 +19,7 @@
>  #include <linux/clk.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/of.h>
> -
> +#include <linux/of_platform.h>
>  #include <drm/exynos_drm.h>
>  #include <plat/regs-fb-v4.h>
> 
> @@ -790,12 +790,56 @@ static int fimd_power_on(struct fimd_context *ctx,
> bool enable)
>  }
> 
>  #ifdef CONFIG_OF
> +
> +#ifdef CONFIG_EXYNOS_IOMMU
> +static int iommu_init(struct device *dev)
> +{
> +	struct platform_device *pds;
> +	struct device_node *dn, *dns;
> +	const __be32 *parp;
> +	int ret;
> +
> +	dn = dev->of_node;
> +	parp = of_get_property(dn, "sysmmu", NULL);
> +	if (parp == NULL) {
> +		dev_err(dev, "failed to find sysmmu property\n");
> +		return -EINVAL;
> +	}
> +	dns = of_find_node_by_phandle(be32_to_cpup(parp));
> +	if (dns == NULL) {
> +		dev_err(dev, "failed to find sysmmu node\n");
> +		return -EINVAL;
> +	}
> +	pds = of_find_device_by_node(dns);
> +	if (pds == NULL) {
> +		dev_err(dev, "failed to find sysmmu platform device\n");
> +		return -EINVAL;
> +	}
> +
> +	platform_set_sysmmu(&pds->dev, dev);
> +	dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL);
> +	if (!dev->dma_parms) {
> +		dev_err(dev, "failed to allocate dma parms\n");
> +		return -ENOMEM;
> +	}
> +	dma_set_max_seg_size(dev, 0xffffffffu);
> +
> +	ret = arm_iommu_attach_device(dev, exynos_drm_common_mapping);

where is exynos_drm_common_mapping declared? you can get this point using
exynos_drm_private structure.


> +	if (ret) {
> +		dev_err(dev, "failed to attach device\n");
> +		return ret;
> +	}
> +	return 0;
> +}
> +#endif
> +

with your patch, we can use iommu feature only with device tree. I think
iommu feature should be used commonly.


>  static struct exynos_drm_fimd_pdata *drm_fimd_dt_parse_pdata(struct
> device *dev)
>  {
>  	struct device_node *np = dev->of_node;
>  	struct device_node *disp_np;
>  	struct exynos_drm_fimd_pdata *pd;
>  	u32 data[4];
> +	int ret;
> 
>  	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
>  	if (!pd) {
> @@ -803,6 +847,14 @@ static struct exynos_drm_fimd_pdata
> *drm_fimd_dt_parse_pdata(struct device *dev)
>  		return ERR_PTR(-ENOMEM);
>  	}
> 
> +#ifdef CONFIG_EXYNOS_IOMMU

and please avoid such #ifdef in device driver.

> +	ret = iommu_init(dev);
> +	if (ret) {
> +		dev_err(dev, "failed to initialize iommu\n");
> +		return ERR_PTR(ret);
> +	}
> +#endif
> +
>  	if (of_get_property(np, "samsung,fimd-vidout-rgb", NULL))
>  		pd->vidcon0 |= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB;
>  	if (of_get_property(np, "samsung,fimd-vidout-tv", NULL))
> --
> 1.7.0.4
diff mbox

Patch

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 15b5286..6d4048a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -19,7 +19,7 @@ 
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
-
+#include <linux/of_platform.h>
 #include <drm/exynos_drm.h>
 #include <plat/regs-fb-v4.h>
 
@@ -790,12 +790,56 @@  static int fimd_power_on(struct fimd_context *ctx, bool enable)
 }
 
 #ifdef CONFIG_OF
+
+#ifdef CONFIG_EXYNOS_IOMMU
+static int iommu_init(struct device *dev)
+{
+	struct platform_device *pds;
+	struct device_node *dn, *dns;
+	const __be32 *parp;
+	int ret;
+
+	dn = dev->of_node;
+	parp = of_get_property(dn, "sysmmu", NULL);
+	if (parp == NULL) {
+		dev_err(dev, "failed to find sysmmu property\n");
+		return -EINVAL;
+	}
+	dns = of_find_node_by_phandle(be32_to_cpup(parp));
+	if (dns == NULL) {
+		dev_err(dev, "failed to find sysmmu node\n");
+		return -EINVAL;
+	}
+	pds = of_find_device_by_node(dns);
+	if (pds == NULL) {
+		dev_err(dev, "failed to find sysmmu platform device\n");
+		return -EINVAL;
+	}
+
+	platform_set_sysmmu(&pds->dev, dev);
+	dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL);
+	if (!dev->dma_parms) {
+		dev_err(dev, "failed to allocate dma parms\n");
+		return -ENOMEM;
+	}
+	dma_set_max_seg_size(dev, 0xffffffffu);
+
+	ret = arm_iommu_attach_device(dev, exynos_drm_common_mapping);
+	if (ret) {
+		dev_err(dev, "failed to attach device\n");
+		return ret;
+	}
+	return 0;
+}
+#endif
+
 static struct exynos_drm_fimd_pdata *drm_fimd_dt_parse_pdata(struct device *dev)
 {
 	struct device_node *np = dev->of_node;
 	struct device_node *disp_np;
 	struct exynos_drm_fimd_pdata *pd;
 	u32 data[4];
+	int ret;
 
 	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
 	if (!pd) {
@@ -803,6 +847,14 @@  static struct exynos_drm_fimd_pdata *drm_fimd_dt_parse_pdata(struct device *dev)
 		return ERR_PTR(-ENOMEM);
 	}
 
+#ifdef CONFIG_EXYNOS_IOMMU
+	ret = iommu_init(dev);
+	if (ret) {
+		dev_err(dev, "failed to initialize iommu\n");
+		return ERR_PTR(ret);
+	}
+#endif
+
 	if (of_get_property(np, "samsung,fimd-vidout-rgb", NULL))
 		pd->vidcon0 |= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB;
 	if (of_get_property(np, "samsung,fimd-vidout-tv", NULL))