Commit | Line | Data |
---|---|---|
0519f9a1 ID |
1 | /* exynos_drm_iommu.c |
2 | * | |
3 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | |
4 | * Author: Inki Dae <inki.dae@samsung.com> | |
5 | * | |
d81aecb5 ID |
6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. | |
0519f9a1 ID |
10 | */ |
11 | ||
4e6319cd | 12 | #include <drm/drmP.h> |
0519f9a1 ID |
13 | #include <drm/exynos_drm.h> |
14 | ||
15 | #include <linux/dma-mapping.h> | |
16 | #include <linux/iommu.h> | |
17 | #include <linux/kref.h> | |
18 | ||
19 | #include <asm/dma-iommu.h> | |
20 | ||
21 | #include "exynos_drm_drv.h" | |
22 | #include "exynos_drm_iommu.h" | |
23 | ||
24 | /* | |
25 | * drm_create_iommu_mapping - create a mapping structure | |
26 | * | |
27 | * @drm_dev: DRM device | |
28 | */ | |
29 | int drm_create_iommu_mapping(struct drm_device *drm_dev) | |
30 | { | |
31 | struct dma_iommu_mapping *mapping = NULL; | |
32 | struct exynos_drm_private *priv = drm_dev->dev_private; | |
0519f9a1 ID |
33 | |
34 | if (!priv->da_start) | |
35 | priv->da_start = EXYNOS_DEV_ADDR_START; | |
36 | if (!priv->da_space_size) | |
37 | priv->da_space_size = EXYNOS_DEV_ADDR_SIZE; | |
0519f9a1 ID |
38 | |
39 | mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start, | |
68efd7d2 MS |
40 | priv->da_space_size); |
41 | ||
a0e41b56 WY |
42 | if (IS_ERR(mapping)) |
43 | return PTR_ERR(mapping); | |
0519f9a1 | 44 | |
f43c3596 | 45 | priv->mapping = mapping; |
0519f9a1 ID |
46 | |
47 | return 0; | |
48 | } | |
49 | ||
50 | /* | |
51 | * drm_release_iommu_mapping - release iommu mapping structure | |
52 | * | |
53 | * @drm_dev: DRM device | |
54 | * | |
55 | * if mapping->kref becomes 0 then all things related to iommu mapping | |
56 | * will be released | |
57 | */ | |
58 | void drm_release_iommu_mapping(struct drm_device *drm_dev) | |
59 | { | |
f43c3596 | 60 | struct exynos_drm_private *priv = drm_dev->dev_private; |
0519f9a1 | 61 | |
f43c3596 | 62 | arm_iommu_release_mapping(priv->mapping); |
0519f9a1 ID |
63 | } |
64 | ||
65 | /* | |
66 | * drm_iommu_attach_device- attach device to iommu mapping | |
67 | * | |
68 | * @drm_dev: DRM device | |
69 | * @subdrv_dev: device to be attach | |
70 | * | |
71 | * This function should be called by sub drivers to attach it to iommu | |
72 | * mapping. | |
73 | */ | |
74 | int drm_iommu_attach_device(struct drm_device *drm_dev, | |
75 | struct device *subdrv_dev) | |
76 | { | |
f43c3596 | 77 | struct exynos_drm_private *priv = drm_dev->dev_private; |
0519f9a1 ID |
78 | int ret; |
79 | ||
f43c3596 | 80 | if (!priv->mapping) |
bf56608a | 81 | return 0; |
0519f9a1 ID |
82 | |
83 | subdrv_dev->dma_parms = devm_kzalloc(subdrv_dev, | |
84 | sizeof(*subdrv_dev->dma_parms), | |
85 | GFP_KERNEL); | |
4db7fcdf SK |
86 | if (!subdrv_dev->dma_parms) |
87 | return -ENOMEM; | |
88 | ||
0519f9a1 ID |
89 | dma_set_max_seg_size(subdrv_dev, 0xffffffffu); |
90 | ||
45286858 MS |
91 | if (subdrv_dev->archdata.mapping) |
92 | arm_iommu_detach_device(subdrv_dev); | |
93 | ||
f43c3596 | 94 | ret = arm_iommu_attach_device(subdrv_dev, priv->mapping); |
0519f9a1 ID |
95 | if (ret < 0) { |
96 | DRM_DEBUG_KMS("failed iommu attach.\n"); | |
97 | return ret; | |
98 | } | |
99 | ||
0519f9a1 ID |
100 | return 0; |
101 | } | |
102 | ||
103 | /* | |
104 | * drm_iommu_detach_device -detach device address space mapping from device | |
105 | * | |
106 | * @drm_dev: DRM device | |
107 | * @subdrv_dev: device to be detached | |
108 | * | |
109 | * This function should be called by sub drivers to detach it from iommu | |
110 | * mapping | |
111 | */ | |
112 | void drm_iommu_detach_device(struct drm_device *drm_dev, | |
113 | struct device *subdrv_dev) | |
114 | { | |
f43c3596 MS |
115 | struct exynos_drm_private *priv = drm_dev->dev_private; |
116 | struct dma_iommu_mapping *mapping = priv->mapping; | |
0519f9a1 ID |
117 | |
118 | if (!mapping || !mapping->domain) | |
119 | return; | |
120 | ||
4d91a855 | 121 | arm_iommu_detach_device(subdrv_dev); |
0519f9a1 | 122 | } |