int arm_iommu_attach_device(struct device *dev,
struct dma_iommu_mapping *mapping);
-
+void arm_iommu_detach_device(struct device *dev,
+ struct dma_iommu_mapping *mapping);
#endif /* __KERNEL__ */
#endif
return mapping;
}
+void s5p_destroy_iommu_mapping(struct device *client)
+{
+ if (!client) {
+ printk(KERN_ERR"Invalid client passed to %s()\n", __func__);
+ return;
+ }
+ /* detach the device from the IOMMU */
+ arm_iommu_detach_device(client, client->archdata.mapping);
+
+ /* release the IOMMU mapping */
+ arm_iommu_release_mapping(client->archdata.mapping);
+
+ return;
+}
+
struct platform_device *find_sysmmu_dt(struct platform_device *pdev,
char *name)
{
struct dma_iommu_mapping *s5p_create_iommu_mapping(struct device *client,
dma_addr_t base, unsigned int size, int order,
struct dma_iommu_mapping *mapping);
+void s5p_destroy_iommu_mapping(struct device *client);
struct platform_device *find_sysmmu_dt(struct platform_device *pdev,
char *name);
pr_info("Attached IOMMU controller to %s device.\n", dev_name(dev));
return 0;
}
-
+/**
+ * @dev: valid struct device pointer
+ * @mapping: io address space mapping structure
+ *
+ * Detaches specified io address space mapping from the provided device
+ */
+void arm_iommu_detach_device(struct device *dev,
+ struct dma_iommu_mapping *mapping)
+{
+ if (!mapping || !mapping->domain) {
+ pr_err("%s(): Trying to detach a device without IOMMU mapping?\n",
+ __func__);
+ return;
+ }
+ iommu_detach_device(mapping->domain, dev);
+ pr_info("Detached IOMMU controller from %s device.\n", dev_name(dev));
+ return;
+}
#endif
return 0;
}
+
+static void iommu_deinit(struct platform_device *pdev)
+{
+ /* detach the device and mapping */
+ s5p_destroy_iommu_mapping(&pdev->dev);
+ DRM_DEBUG("released the IOMMU mapping\n");
+
+ return;
+}
#endif
static int exynos_drm_platform_probe(struct platform_device *pdev)
return drm_platform_init(&exynos_drm_driver, pdev);
}
-static int exynos_drm_platform_remove(struct platform_device *pdev)
+static int __devexit exynos_drm_platform_remove(struct platform_device *pdev)
{
DRM_DEBUG_DRIVER("%s\n", __FILE__);
drm_platform_exit(&exynos_drm_driver, pdev);
+#ifdef CONFIG_EXYNOS_IOMMU
+ iommu_deinit(pdev);
+#endif
return 0;
}
return 0;
}
+
+static void iommu_deinit(struct platform_device *pdev)
+{
+ s5p_destroy_iommu_mapping(&pdev->dev);
+ DRM_DEBUG("released the IOMMU mapping\n");
+
+ return;
+}
#endif
+
static int __devinit fimd_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
clk_put(ctx->bus_clk);
err_clk_get:
+#ifdef CONFIG_EXYNOS_IOMMU
+ iommu_deinit(pdev);
+#endif
kfree(ctx);
return ret;
}
release_resource(ctx->regs_res);
kfree(ctx->regs_res);
free_irq(ctx->irq, ctx);
-
+#ifdef CONFIG_EXYNOS_IOMMU
+ iommu_deinit(pdev);
+#endif
kfree(ctx);
return 0;
return 0;
}
+
+static void iommu_deinit(struct platform_device *pdev)
+{
+ s5p_destroy_iommu_mapping(&pdev->dev);
+ printk(KERN_INFO"released the IOMMU mapping\n");
+
+ return;
+}
#endif
static int gsc_probe(struct platform_device *pdev)
{
release_resource(gsc->regs_res);
kfree(gsc->regs_res);
err_info:
+#ifdef CONFIG_EXYNOS_IOMMU
+ iommu_deinit(pdev);
+#endif
kfree(gsc);
return ret;
release_resource(gsc->regs_res);
kfree(gsc->regs_res);
kfree(gsc);
-
+#ifdef CONFIG_EXYNOS_IOMMU
+ iommu_deinit(pdev);
+#endif
dev_info(&pdev->dev, "%s driver unloaded\n", pdev->name);
return 0;
}
return 0;
}
+
+static void iommu_deinit(struct platform_device *pdev)
+{
+ s5p_destroy_iommu_mapping(&pdev->dev);
+ printk(KERN_INFO"released the IOMMU mapping\n");
+
+ return;
+}
#endif
/* --------- DRIVER INITIALIZATION ---------- */
fail_mem:
kfree(mdev);
-
+#ifdef CONFIG_EXYNOS_IOMMU
+ iommu_deinit(pdev);
+#endif
fail:
dev_info(dev, "probe failed\n");
return ret;
mxr_release_layers(mdev);
mxr_release_video(mdev);
mxr_release_resources(mdev);
-
+#ifdef CONFIG_EXYNOS_IOMMU
+ iommu_deinit(pdev);
+#endif
kfree(mdev);
dev_info(dev, "remove sucessful\n");
return 0;
}
+
+static void iommu_deinit(struct device *mfc_l, struct device *mfc_r)
+{
+ s5p_destroy_iommu_mapping(mfc_l);
+ printk(KERN_INFO"released the IOMMU mapping for MFC_L\n");
+
+ s5p_destroy_iommu_mapping(mfc_r);
+ printk(KERN_INFO"released the IOMMU mapping for MFC_R\n");
+
+ return;
+}
#endif
/* MFC probe function */
err_mem_init_ctx_1:
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
err_mem_init_ctx_0:
+#ifdef CONFIG_EXYNOS_IOMMU
+ iommu_deinit(dev->mem_dev_r, dev->mem_dev_l);
+#endif
err_iommu_init:
free_irq(dev->irq, dev);
err_req_irq:
v4l2_device_unregister(&dev->v4l2_dev);
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
-
+#ifdef CONFIG_EXYNOS_IOMMU
+ iommu_deinit(dev->mem_dev_r, dev->mem_dev_l);
+#endif
free_irq(dev->irq, dev);
iounmap(dev->regs_base);
if (dev->mfc_mem) {