diff options
author | Susheel Khiani <skhiani@codeaurora.org> | 2016-02-04 17:08:19 +0530 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 21:25:36 -0700 |
commit | a6fba6085dd06a63edfaf0ed93acee72cbfabc60 (patch) | |
tree | a9d2020b332454afb118198f5131fd0f2046b870 /drivers | |
parent | 84072b90d254c9597c06b360fdfc3a51e03eba95 (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')
-rw-r--r-- | drivers/iommu/arm-smmu.c | 30 |
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); |