aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShunqian Zheng <zhengsq@rock-chips.com>2016-06-23 22:13:32 -0400
committerMark Yao <mark.yao@rock-chips.com>2017-02-14 19:52:13 -0500
commit1aa5ca6e3ec63aa5815d78646748e88a7ceb1c8e (patch)
tree51cbbeb3eefd0be40581fd7e27366e3a3ae63b5a
parent38f993b7c59e261b8ff7deb66c96c7dff4017f7b (diff)
drm/rockchip: Use common IOMMU API to attach devices
Rockchip DRM used the arm special API, arm_iommu_*(), to attach iommu for ARM32 SoCs. This patch convert to common iommu API so it would support ARM64 like RK3399. Since previous patch added support for direct IOMMU address space management, there is no need to use DMA API anymore and this patch wires things to use the new method. Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com> Signed-off-by: Tomasz Figa <tfiga@chromium.org> Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c101
1 files changed, 54 insertions, 47 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index c30d649cb147..b360e6251836 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -14,19 +14,19 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 */ 15 */
16 16
17#include <asm/dma-iommu.h>
18
19#include <drm/drmP.h> 17#include <drm/drmP.h>
20#include <drm/drm_crtc_helper.h> 18#include <drm/drm_crtc_helper.h>
21#include <drm/drm_fb_helper.h> 19#include <drm/drm_fb_helper.h>
22#include <drm/drm_gem_cma_helper.h> 20#include <drm/drm_gem_cma_helper.h>
23#include <drm/drm_of.h> 21#include <drm/drm_of.h>
24#include <linux/dma-mapping.h> 22#include <linux/dma-mapping.h>
23#include <linux/dma-iommu.h>
25#include <linux/pm_runtime.h> 24#include <linux/pm_runtime.h>
26#include <linux/module.h> 25#include <linux/module.h>
27#include <linux/of_graph.h> 26#include <linux/of_graph.h>
28#include <linux/component.h> 27#include <linux/component.h>
29#include <linux/console.h> 28#include <linux/console.h>
29#include <linux/iommu.h>
30 30
31#include "rockchip_drm_drv.h" 31#include "rockchip_drm_drv.h"
32#include "rockchip_drm_fb.h" 32#include "rockchip_drm_fb.h"
@@ -50,28 +50,31 @@ static struct drm_driver rockchip_drm_driver;
50int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, 50int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
51 struct device *dev) 51 struct device *dev)
52{ 52{
53 struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping; 53 struct rockchip_drm_private *private = drm_dev->dev_private;
54 int ret; 54 int ret;
55 55
56 if (!is_support_iommu) 56 if (!is_support_iommu)
57 return 0; 57 return 0;
58 58
59 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); 59 ret = iommu_attach_device(private->domain, dev);
60 if (ret) 60 if (ret) {
61 dev_err(dev, "Failed to attach iommu device\n");
61 return ret; 62 return ret;
63 }
62 64
63 dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); 65 return 0;
64
65 return arm_iommu_attach_device(dev, mapping);
66} 66}
67 67
68void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, 68void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
69 struct device *dev) 69 struct device *dev)
70{ 70{
71 struct rockchip_drm_private *private = drm_dev->dev_private;
72 struct iommu_domain *domain = private->domain;
73
71 if (!is_support_iommu) 74 if (!is_support_iommu)
72 return; 75 return;
73 76
74 arm_iommu_detach_device(dev); 77 iommu_detach_device(domain, dev);
75} 78}
76 79
77int rockchip_register_crtc_funcs(struct drm_crtc *crtc, 80int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -123,11 +126,46 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev,
123 priv->crtc_funcs[pipe]->disable_vblank(crtc); 126 priv->crtc_funcs[pipe]->disable_vblank(crtc);
124} 127}
125 128
129static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
130{
131 struct rockchip_drm_private *private = drm_dev->dev_private;
132 struct iommu_domain_geometry *geometry;
133 u64 start, end;
134
135 if (!is_support_iommu)
136 return 0;
137
138 private->domain = iommu_domain_alloc(&platform_bus_type);
139 if (!private->domain)
140 return -ENOMEM;
141
142 geometry = &private->domain->geometry;
143 start = geometry->aperture_start;
144 end = geometry->aperture_end;
145
146 DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n",
147 start, end);
148 drm_mm_init(&private->mm, start, end - start + 1);
149 mutex_init(&private->mm_lock);
150
151 return 0;
152}
153
154static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
155{
156 struct rockchip_drm_private *private = drm_dev->dev_private;
157
158 if (!is_support_iommu)
159 return;
160
161 drm_mm_takedown(&private->mm);
162 iommu_domain_free(private->domain);
163}
164
126static int rockchip_drm_bind(struct device *dev) 165static int rockchip_drm_bind(struct device *dev)
127{ 166{
128 struct drm_device *drm_dev; 167 struct drm_device *drm_dev;
129 struct rockchip_drm_private *private; 168 struct rockchip_drm_private *private;
130 struct dma_iommu_mapping *mapping = NULL;
131 int ret; 169 int ret;
132 170
133 drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev); 171 drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev);
@@ -151,38 +189,14 @@ static int rockchip_drm_bind(struct device *dev)
151 189
152 rockchip_drm_mode_config_init(drm_dev); 190 rockchip_drm_mode_config_init(drm_dev);
153 191
154 dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), 192 ret = rockchip_drm_init_iommu(drm_dev);
155 GFP_KERNEL); 193 if (ret)
156 if (!dev->dma_parms) {
157 ret = -ENOMEM;
158 goto err_config_cleanup; 194 goto err_config_cleanup;
159 }
160
161 if (is_support_iommu) {
162 /* TODO(djkurtz): fetch the mapping start/size from somewhere */
163 mapping = arm_iommu_create_mapping(&platform_bus_type,
164 0x00000000,
165 SZ_2G);
166 if (IS_ERR(mapping)) {
167 ret = PTR_ERR(mapping);
168 goto err_config_cleanup;
169 }
170
171 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
172 if (ret)
173 goto err_release_mapping;
174
175 dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
176
177 ret = arm_iommu_attach_device(dev, mapping);
178 if (ret)
179 goto err_release_mapping;
180 }
181 195
182 /* Try to bind all sub drivers. */ 196 /* Try to bind all sub drivers. */
183 ret = component_bind_all(dev, drm_dev); 197 ret = component_bind_all(dev, drm_dev);
184 if (ret) 198 if (ret)
185 goto err_detach_device; 199 goto err_iommu_cleanup;
186 200
187 /* init kms poll for handling hpd */ 201 /* init kms poll for handling hpd */
188 drm_kms_helper_poll_init(drm_dev); 202 drm_kms_helper_poll_init(drm_dev);
@@ -207,8 +221,6 @@ static int rockchip_drm_bind(struct device *dev)
207 if (ret) 221 if (ret)
208 goto err_fbdev_fini; 222 goto err_fbdev_fini;
209 223
210 if (is_support_iommu)
211 arm_iommu_release_mapping(mapping);
212 return 0; 224 return 0;
213err_fbdev_fini: 225err_fbdev_fini:
214 rockchip_drm_fbdev_fini(drm_dev); 226 rockchip_drm_fbdev_fini(drm_dev);
@@ -217,12 +229,8 @@ err_vblank_cleanup:
217err_kms_helper_poll_fini: 229err_kms_helper_poll_fini:
218 drm_kms_helper_poll_fini(drm_dev); 230 drm_kms_helper_poll_fini(drm_dev);
219 component_unbind_all(dev, drm_dev); 231 component_unbind_all(dev, drm_dev);
220err_detach_device: 232err_iommu_cleanup:
221 if (is_support_iommu) 233 rockchip_iommu_cleanup(drm_dev);
222 arm_iommu_detach_device(dev);
223err_release_mapping:
224 if (is_support_iommu)
225 arm_iommu_release_mapping(mapping);
226err_config_cleanup: 234err_config_cleanup:
227 drm_mode_config_cleanup(drm_dev); 235 drm_mode_config_cleanup(drm_dev);
228 drm_dev->dev_private = NULL; 236 drm_dev->dev_private = NULL;
@@ -239,8 +247,7 @@ static void rockchip_drm_unbind(struct device *dev)
239 drm_vblank_cleanup(drm_dev); 247 drm_vblank_cleanup(drm_dev);
240 drm_kms_helper_poll_fini(drm_dev); 248 drm_kms_helper_poll_fini(drm_dev);
241 component_unbind_all(dev, drm_dev); 249 component_unbind_all(dev, drm_dev);
242 if (is_support_iommu) 250 rockchip_iommu_cleanup(drm_dev);
243 arm_iommu_detach_device(dev);
244 drm_mode_config_cleanup(drm_dev); 251 drm_mode_config_cleanup(drm_dev);
245 drm_dev->dev_private = NULL; 252 drm_dev->dev_private = NULL;
246 drm_dev_unregister(drm_dev); 253 drm_dev_unregister(drm_dev);