summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJordan Crouse <jcrouse@codeaurora.org>2017-02-13 10:14:32 -0700
committerJordan Crouse <jcrouse@codeaurora.org>2017-02-22 09:52:32 -0700
commit9f8cd5dfb437c689b563c6e9a2d3d4316655ab28 (patch)
tree59fe013135d33c2de08498dc871646cb0e12d6e4 /drivers/gpu
parent4b508ebeb81e6908d8c2eb359e90329f661ecdac (diff)
drm/msm: Get and enable the IOMMU clocks
If we do not enable the iommu clocks at attach time they might be shut off automatically by other devices power collapsing which would affect our ability to switch the pagetable dynamically. There is little power downside to just leaving them on all the time, or at least as long as the main device is attached (in other words, all the time). Change-Id: Ic0dedbad8f6d2ee2a2cb9516e062af2421d91052 Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c60
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.h5
2 files changed, 63 insertions, 2 deletions
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index acbab7494de4..3c16222b8890 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -26,6 +26,47 @@ static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
return 0;
}
+/*
+ * Get and enable the IOMMU clocks so that we can make
+ * sure they stay on the entire duration so that we can
+ * safely change the pagetable from the GPU
+ */
+static void _get_iommu_clocks(struct msm_mmu *mmu, struct platform_device *pdev)
+{
+ struct msm_iommu *iommu = to_msm_iommu(mmu);
+ struct device *dev;
+ struct property *prop;
+ const char *name;
+ int i = 0;
+
+ if (WARN_ON(!pdev))
+ return;
+
+ dev = &pdev->dev;
+
+ iommu->nr_clocks =
+ of_property_count_strings(dev->of_node, "clock-names");
+
+ if (iommu->nr_clocks < 0) {
+ iommu->nr_clocks = 0;
+ return;
+ }
+
+ if (WARN_ON(iommu->nr_clocks > ARRAY_SIZE(iommu->clocks)))
+ iommu->nr_clocks = ARRAY_SIZE(iommu->clocks);
+
+ of_property_for_each_string(dev->of_node, "clock-names", prop, name) {
+ if (i == iommu->nr_clocks)
+ break;
+
+ iommu->clocks[i] = clk_get(dev, name);
+ if (iommu->clocks[i])
+ clk_prepare_enable(iommu->clocks[i]);
+
+ i++;
+ }
+}
+
static int _attach_iommu_device(struct msm_mmu *mmu,
struct iommu_domain *domain, const char **names, int cnt)
{
@@ -58,7 +99,11 @@ static int _attach_iommu_device(struct msm_mmu *mmu,
if (!pdev)
continue;
+ _get_iommu_clocks(mmu,
+ of_find_device_by_node(node->parent));
+
mmu->dev = &pdev->dev;
+
return iommu_attach_device(domain, mmu->dev);
}
}
@@ -130,6 +175,19 @@ static int msm_iommu_attach_dynamic(struct msm_mmu *mmu, const char **names,
static void msm_iommu_detach(struct msm_mmu *mmu)
{
struct msm_iommu *iommu = to_msm_iommu(mmu);
+ int i;
+
+ iommu_detach_device(iommu->domain, mmu->dev);
+
+ for (i = 0; i < iommu->nr_clocks; i++) {
+ if (iommu->clocks[i])
+ clk_disable(iommu->clocks[i]);
+ }
+}
+
+static void msm_iommu_detach_dynamic(struct msm_mmu *mmu)
+{
+ struct msm_iommu *iommu = to_msm_iommu(mmu);
iommu_detach_device(iommu->domain, mmu->dev);
}
@@ -216,7 +274,7 @@ static const struct msm_mmu_funcs funcs = {
static const struct msm_mmu_funcs dynamic_funcs = {
.attach = msm_iommu_attach_dynamic,
- .detach = msm_iommu_detach,
+ .detach = msm_iommu_detach_dynamic,
.map = msm_iommu_map,
.unmap = msm_iommu_unmap,
.destroy = msm_iommu_destroy,
diff --git a/drivers/gpu/drm/msm/msm_iommu.h b/drivers/gpu/drm/msm/msm_iommu.h
index bfb75015efbc..d005cfb9758f 100644
--- a/drivers/gpu/drm/msm/msm_iommu.h
+++ b/drivers/gpu/drm/msm/msm_iommu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -22,6 +22,9 @@ struct msm_iommu {
phys_addr_t ttbr0;
uint32_t contextidr;
bool allow_dynamic;
+
+ struct clk *clocks[5];
+ int nr_clocks;
};
#define to_msm_iommu(x) container_of(x, struct msm_iommu, base)