summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchel Humpherys <mitchelh@codeaurora.org>2014-08-06 18:21:00 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:11:07 -0700
commite400e3338906fd38e408d44f0d20e18d3b715f2c (patch)
tree4ba12134d5bb19b2c8e119fd2086a52144743666
parent40cd28528c4980a748bbea04dd628f46c3b7ef41 (diff)
iommu/arm-smmu: support buggy implementations with invalidate-on-map
Add a workaround for some buggy hardware that requires a TLB invalidate operation to occur at map time. Activate the feature with the qcom,smmu-invalidate-on-map boolean DT property. Change-Id: I081a279fead983ae3d736b44cda371078e55a750 Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/iommu/arm,smmu.txt4
-rw-r--r--drivers/iommu/arm-smmu.c14
2 files changed, 17 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index d47d42f525e1..2df61831092f 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -55,6 +55,10 @@ conditions.
aliases of secure registers have to be used during
SMMU configuration.
+- qcom,smmu-invalidate-on-map : Enable proper handling of buggy
+ implementations that require a TLB invalidate
+ operation to occur at map time.
+
- clocks : List of clocks to be used during SMMU register access. See
Documentation/devicetree/bindings/clock/clock-bindings.txt
for information about the format. For each clock specified
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 2ac692a0137d..69ac1480db1b 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -382,6 +382,7 @@ struct arm_smmu_device {
u32 features;
#define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
+#define ARM_SMMU_OPT_INVALIDATE_ON_MAP (1 << 1)
u32 options;
enum arm_smmu_arch_version version;
@@ -441,6 +442,7 @@ struct arm_smmu_option_prop {
static struct arm_smmu_option_prop arm_smmu_options[] = {
{ ARM_SMMU_OPT_SECURE_CFG_ACCESS, "calxeda,smmu-secure-config-access" },
+ { ARM_SMMU_OPT_INVALIDATE_ON_MAP, "qcom,smmu-invalidate-on-map" },
{ 0, NULL},
};
@@ -1678,12 +1680,22 @@ out_unlock:
static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
{
+ int ret;
struct arm_smmu_domain *smmu_domain = domain->priv;
if (!smmu_domain)
return -ENODEV;
- return arm_smmu_handle_mapping(smmu_domain, iova, paddr, size, prot);
+ ret = arm_smmu_handle_mapping(smmu_domain, iova, paddr, size, prot);
+
+ if (!ret &&
+ (smmu_domain->smmu->options & ARM_SMMU_OPT_INVALIDATE_ON_MAP)) {
+ arm_smmu_enable_clocks(smmu_domain->smmu);
+ arm_smmu_tlb_inv_context(smmu_domain);
+ arm_smmu_disable_clocks(smmu_domain->smmu);
+ }
+
+ return ret;
}
static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,