diff options
| author | 2017-05-05 11:47:01 +1000 | |
|---|---|---|
| committer | 2017-05-05 11:47:01 +1000 | |
| commit | 644b4930bf7e2adeffbe842e1097f7933c6a9158 (patch) | |
| tree | dcb9e56d30af9b590c511f89b0b6815dd67321e6 /drivers/gpu/host1x/dev.c | |
| parent | Merge branch 'linux-4.12' of git://github.com/skeggsb/linux into drm-next (diff) | |
| parent | gpu: host1x: Fix host1x driver shutdown (diff) | |
Merge tag 'drm/tegra/for-4.12-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/tegra: Changes for v4.12-rc1
This contains various fixes to the host1x driver as well as a plug for a
leak of kernel pointers to userspace.
A fairly big addition this time around is the Video Image Composer (VIC)
support that can be used to accelerate some 2D and image compositing
operations.
Furthermore the driver now supports FB modifiers, so we no longer rely
on a custom IOCTL to set those.
Finally this contains a few preparatory patches for Tegra186 support
which unfortunately didn't quite make it this time, but will hopefully
be ready for v4.13.
* tag 'drm/tegra/for-4.12-rc1' of git://anongit.freedesktop.org/tegra/linux:
gpu: host1x: Fix host1x driver shutdown
gpu: host1x: Support module reset
gpu: host1x: Sort includes alphabetically
drm/tegra: Add VIC support
dt-bindings: Add bindings for the Tegra VIC
drm/tegra: Add falcon helper library
drm/tegra: Add Tegra DRM allocation API
drm/tegra: Add tiling FB modifiers
drm/tegra: Don't leak kernel pointer to userspace
drm/tegra: Protect IOMMU operations by mutex
drm/tegra: Enable IOVA API when IOMMU support is enabled
gpu: host1x: Add IOMMU support
gpu: host1x: Fix potential out-of-bounds access
iommu/iova: Fix compile error with CONFIG_IOMMU_IOVA=m
iommu: Add dummy implementations for !IOMMU_IOVA
MAINTAINERS: Add related headers to IOMMU section
iommu/iova: Consolidate code for adding new node to iovad domain rbtree
Diffstat (limited to 'drivers/gpu/host1x/dev.c')
| -rw-r--r-- | drivers/gpu/host1x/dev.c | 76 |
1 files changed, 65 insertions, 11 deletions
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index a62317af76ad..f05ebb14fa63 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -16,23 +16,25 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <linux/module.h> -#include <linux/list.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_device.h> #include <linux/clk.h> -#include <linux/io.h> #include <linux/dma-mapping.h> +#include <linux/io.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/slab.h> #define CREATE_TRACE_POINTS #include <trace/events/host1x.h> +#undef CREATE_TRACE_POINTS #include "bus.h" -#include "dev.h" -#include "intr.h" #include "channel.h" #include "debug.h" +#include "dev.h" +#include "intr.h" + #include "hw/host1x01.h" #include "hw/host1x02.h" #include "hw/host1x04.h" @@ -168,22 +170,56 @@ static int host1x_probe(struct platform_device *pdev) return err; } + host->rst = devm_reset_control_get(&pdev->dev, "host1x"); + if (IS_ERR(host->rst)) { + err = PTR_ERR(host->clk); + dev_err(&pdev->dev, "failed to get reset: %d\n", err); + return err; + } + + if (iommu_present(&platform_bus_type)) { + struct iommu_domain_geometry *geometry; + unsigned long order; + + host->domain = iommu_domain_alloc(&platform_bus_type); + if (!host->domain) + return -ENOMEM; + + err = iommu_attach_device(host->domain, &pdev->dev); + if (err) + goto fail_free_domain; + + geometry = &host->domain->geometry; + + order = __ffs(host->domain->pgsize_bitmap); + init_iova_domain(&host->iova, 1UL << order, + geometry->aperture_start >> order, + geometry->aperture_end >> order); + host->iova_end = geometry->aperture_end; + } + err = host1x_channel_list_init(host); if (err) { dev_err(&pdev->dev, "failed to initialize channel list\n"); - return err; + goto fail_detach_device; } err = clk_prepare_enable(host->clk); if (err < 0) { dev_err(&pdev->dev, "failed to enable clock\n"); - return err; + goto fail_detach_device; + } + + err = reset_control_deassert(host->rst); + if (err < 0) { + dev_err(&pdev->dev, "failed to deassert reset: %d\n", err); + goto fail_unprepare_disable; } err = host1x_syncpt_init(host); if (err) { dev_err(&pdev->dev, "failed to initialize syncpts\n"); - goto fail_unprepare_disable; + goto fail_reset_assert; } err = host1x_intr_init(host, syncpt_irq); @@ -204,8 +240,19 @@ fail_deinit_intr: host1x_intr_deinit(host); fail_deinit_syncpt: host1x_syncpt_deinit(host); +fail_reset_assert: + reset_control_assert(host->rst); fail_unprepare_disable: clk_disable_unprepare(host->clk); +fail_detach_device: + if (host->domain) { + put_iova_domain(&host->iova); + iommu_detach_device(host->domain, &pdev->dev); + } +fail_free_domain: + if (host->domain) + iommu_domain_free(host->domain); + return err; } @@ -216,8 +263,15 @@ static int host1x_remove(struct platform_device *pdev) host1x_unregister(host); host1x_intr_deinit(host); host1x_syncpt_deinit(host); + reset_control_assert(host->rst); clk_disable_unprepare(host->clk); + if (host->domain) { + put_iova_domain(&host->iova); + iommu_detach_device(host->domain, &pdev->dev); + iommu_domain_free(host->domain); + } + return 0; } |
