summaryrefslogtreecommitdiff
path: root/drivers/iommu/arm-smmu.c
diff options
context:
space:
mode:
authorSusheel Khiani <skhiani@codeaurora.org>2016-02-04 17:08:19 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:25:36 -0700
commita6fba6085dd06a63edfaf0ed93acee72cbfabc60 (patch)
treea9d2020b332454afb118198f5131fd0f2046b870 /drivers/iommu/arm-smmu.c
parent84072b90d254c9597c06b360fdfc3a51e03eba95 (diff)
iommu/arm-smmu: Make atomic scm call in slave side protection mode
When we have SMMU halt/resume functionality enabled we try to program MICRO_MMU_CTRL register which is part of SMMU implementation defined register space. Now targets which have slave side protection mechanism, implementation defined register space of SMMU is protected by XPUs along with other SMMU global register space. As a result we would get a fault if we directly try to program MICRO_MMU_CTRL register. Instead we request TZ through atomic scm call to program this register for us. Since we have read only permission available for these registers we need to ensure that write operation is requested through TZ. CRs-Fixed: 959535 Change-Id: Ie257553a25bb11785b69568d8eccbef91d8d18e0 Signed-off-by: Susheel Khiani <skhiani@codeaurora.org>
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r--drivers/iommu/arm-smmu.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index b71fe57d62bf..371b241cd190 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -342,6 +342,7 @@ struct arm_smmu_device {
void __iomem *base;
unsigned long size;
+ phys_addr_t phys_addr;
unsigned long pgshift;
#define ARM_SMMU_FEAT_COHERENT_WALK (1 << 0)
@@ -2491,7 +2492,20 @@ static int __arm_smmu_halt(struct arm_smmu_device *smmu, bool wait)
reg = readl_relaxed(impl_def1_base + IMPL_DEF1_MICRO_MMU_CTRL);
reg |= MICRO_MMU_CTRL_LOCAL_HALT_REQ;
- writel_relaxed(reg, impl_def1_base + IMPL_DEF1_MICRO_MMU_CTRL);
+
+ if (arm_smmu_is_static_cb(smmu)) {
+ phys_addr_t impl_def1_base_phys = impl_def1_base - smmu->base +
+ smmu->phys_addr;
+
+ if (scm_io_write(impl_def1_base_phys +
+ IMPL_DEF1_MICRO_MMU_CTRL, reg)) {
+ dev_err(smmu->dev,
+ "scm_io_write fail. SMMU might not be halted");
+ return -EINVAL;
+ }
+ } else {
+ writel_relaxed(reg, impl_def1_base + IMPL_DEF1_MICRO_MMU_CTRL);
+ }
return wait ? arm_smmu_wait_for_halt(smmu) : 0;
}
@@ -2523,7 +2537,18 @@ static void arm_smmu_resume(struct arm_smmu_device *smmu)
reg = readl_relaxed(impl_def1_base + IMPL_DEF1_MICRO_MMU_CTRL);
reg &= ~MICRO_MMU_CTRL_LOCAL_HALT_REQ;
- writel_relaxed(reg, impl_def1_base + IMPL_DEF1_MICRO_MMU_CTRL);
+
+ if (arm_smmu_is_static_cb(smmu)) {
+ phys_addr_t impl_def1_base_phys = impl_def1_base - smmu->base +
+ smmu->phys_addr;
+
+ if (scm_io_write(impl_def1_base_phys +
+ IMPL_DEF1_MICRO_MMU_CTRL, reg))
+ dev_err(smmu->dev,
+ "scm_io_write fail. SMMU might not be resumed");
+ } else {
+ writel_relaxed(reg, impl_def1_base + IMPL_DEF1_MICRO_MMU_CTRL);
+ }
}
static phys_addr_t __arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
@@ -3496,6 +3521,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
smmu->version = (enum arm_smmu_arch_version)of_id->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ smmu->phys_addr = res->start;
smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);