diff options
author | Mikko Perttunen <mperttunen@nvidia.com> | 2016-12-14 06:16:14 -0500 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2017-04-05 12:11:43 -0400 |
commit | 404bfb78daf3bedafb0bfab24947059575cbea3d (patch) | |
tree | 59b8ed6b140ce74ffeb94e1488ee7818f3b02c18 /drivers/gpu/host1x/dev.c | |
parent | 8cadb01d2c2f520a890d1bc78b45471f21b9b76d (diff) |
gpu: host1x: Add IOMMU support
Add support for the Host1x unit to be located behind
an IOMMU. This is required when gather buffers may be
allocated non-contiguously in physical memory, as can
be the case when TegraDRM is also using the IOMMU.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/host1x/dev.c')
-rw-r--r-- | drivers/gpu/host1x/dev.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index a62317af76ad..b386a0bf828a 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | #define CREATE_TRACE_POINTS | 28 | #define CREATE_TRACE_POINTS |
29 | #include <trace/events/host1x.h> | 29 | #include <trace/events/host1x.h> |
30 | #undef CREATE_TRACE_POINTS | ||
30 | 31 | ||
31 | #include "bus.h" | 32 | #include "bus.h" |
32 | #include "dev.h" | 33 | #include "dev.h" |
@@ -168,16 +169,37 @@ static int host1x_probe(struct platform_device *pdev) | |||
168 | return err; | 169 | return err; |
169 | } | 170 | } |
170 | 171 | ||
172 | if (iommu_present(&platform_bus_type)) { | ||
173 | struct iommu_domain_geometry *geometry; | ||
174 | unsigned long order; | ||
175 | |||
176 | host->domain = iommu_domain_alloc(&platform_bus_type); | ||
177 | if (!host->domain) | ||
178 | return -ENOMEM; | ||
179 | |||
180 | err = iommu_attach_device(host->domain, &pdev->dev); | ||
181 | if (err) | ||
182 | goto fail_free_domain; | ||
183 | |||
184 | geometry = &host->domain->geometry; | ||
185 | |||
186 | order = __ffs(host->domain->pgsize_bitmap); | ||
187 | init_iova_domain(&host->iova, 1UL << order, | ||
188 | geometry->aperture_start >> order, | ||
189 | geometry->aperture_end >> order); | ||
190 | host->iova_end = geometry->aperture_end; | ||
191 | } | ||
192 | |||
171 | err = host1x_channel_list_init(host); | 193 | err = host1x_channel_list_init(host); |
172 | if (err) { | 194 | if (err) { |
173 | dev_err(&pdev->dev, "failed to initialize channel list\n"); | 195 | dev_err(&pdev->dev, "failed to initialize channel list\n"); |
174 | return err; | 196 | goto fail_detach_device; |
175 | } | 197 | } |
176 | 198 | ||
177 | err = clk_prepare_enable(host->clk); | 199 | err = clk_prepare_enable(host->clk); |
178 | if (err < 0) { | 200 | if (err < 0) { |
179 | dev_err(&pdev->dev, "failed to enable clock\n"); | 201 | dev_err(&pdev->dev, "failed to enable clock\n"); |
180 | return err; | 202 | goto fail_detach_device; |
181 | } | 203 | } |
182 | 204 | ||
183 | err = host1x_syncpt_init(host); | 205 | err = host1x_syncpt_init(host); |
@@ -206,6 +228,15 @@ fail_deinit_syncpt: | |||
206 | host1x_syncpt_deinit(host); | 228 | host1x_syncpt_deinit(host); |
207 | fail_unprepare_disable: | 229 | fail_unprepare_disable: |
208 | clk_disable_unprepare(host->clk); | 230 | clk_disable_unprepare(host->clk); |
231 | fail_detach_device: | ||
232 | if (host->domain) { | ||
233 | put_iova_domain(&host->iova); | ||
234 | iommu_detach_device(host->domain, &pdev->dev); | ||
235 | } | ||
236 | fail_free_domain: | ||
237 | if (host->domain) | ||
238 | iommu_domain_free(host->domain); | ||
239 | |||
209 | return err; | 240 | return err; |
210 | } | 241 | } |
211 | 242 | ||
@@ -218,6 +249,12 @@ static int host1x_remove(struct platform_device *pdev) | |||
218 | host1x_syncpt_deinit(host); | 249 | host1x_syncpt_deinit(host); |
219 | clk_disable_unprepare(host->clk); | 250 | clk_disable_unprepare(host->clk); |
220 | 251 | ||
252 | if (host->domain) { | ||
253 | put_iova_domain(&host->iova); | ||
254 | iommu_detach_device(host->domain, &pdev->dev); | ||
255 | iommu_domain_free(host->domain); | ||
256 | } | ||
257 | |||
221 | return 0; | 258 | return 0; |
222 | } | 259 | } |
223 | 260 | ||