diff options
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r-- | drivers/iommu/arm-smmu.c | 53 |
1 files changed, 13 insertions, 40 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 9f7e1d34a32b..dce041b1c139 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -202,8 +202,7 @@ #define ARM_SMMU_CB_S1_TLBIVAL 0x620 #define ARM_SMMU_CB_S2_TLBIIPAS2 0x630 #define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638 -#define ARM_SMMU_CB_ATS1PR_LO 0x800 -#define ARM_SMMU_CB_ATS1PR_HI 0x804 +#define ARM_SMMU_CB_ATS1PR 0x800 #define ARM_SMMU_CB_ATSR 0x8f0 #define SCTLR_S1_ASIDPNE (1 << 12) @@ -224,14 +223,7 @@ #define RESUME_TERMINATE (1 << 0) #define TTBCR2_SEP_SHIFT 15 -#define TTBCR2_SEP_MASK 0x7 - -#define TTBCR2_ADDR_32 0 -#define TTBCR2_ADDR_36 1 -#define TTBCR2_ADDR_40 2 -#define TTBCR2_ADDR_42 3 -#define TTBCR2_ADDR_44 4 -#define TTBCR2_ADDR_48 5 +#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT) #define TTBRn_HI_ASID_SHIFT 16 @@ -254,7 +246,7 @@ #define FSYNR0_WNR (1 << 4) static int force_stage; -module_param_named(force_stage, force_stage, int, S_IRUGO | S_IWUSR); +module_param_named(force_stage, force_stage, int, S_IRUGO); MODULE_PARM_DESC(force_stage, "Force SMMU mappings to be installed at a particular stage of translation. A value of '1' or '2' forces the corresponding stage. All other values are ignored (i.e. no stage is forced). Note that selecting a specific stage will disable support for nested translation."); @@ -793,26 +785,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR); if (smmu->version > ARM_SMMU_V1) { reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32; - switch (smmu->va_size) { - case 32: - reg |= (TTBCR2_ADDR_32 << TTBCR2_SEP_SHIFT); - break; - case 36: - reg |= (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT); - break; - case 40: - reg |= (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT); - break; - case 42: - reg |= (TTBCR2_ADDR_42 << TTBCR2_SEP_SHIFT); - break; - case 44: - reg |= (TTBCR2_ADDR_44 << TTBCR2_SEP_SHIFT); - break; - case 48: - reg |= (TTBCR2_ADDR_48 << TTBCR2_SEP_SHIFT); - break; - } + reg |= TTBCR2_SEP_UPSTREAM; writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR2); } } else { @@ -1255,18 +1228,18 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, void __iomem *cb_base; u32 tmp; u64 phys; + unsigned long va; cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx); - if (smmu->version == 1) { - u32 reg = iova & ~0xfff; - writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO); - } else { - u32 reg = iova & ~0xfff; - writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO); - reg = ((u64)iova & ~0xfff) >> 32; - writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_HI); - } + /* ATS1 registers can only be written atomically */ + va = iova & ~0xfffUL; +#ifdef CONFIG_64BIT + if (smmu->version == ARM_SMMU_V2) + writeq_relaxed(va, cb_base + ARM_SMMU_CB_ATS1PR); + else +#endif + writel_relaxed(va, cb_base + ARM_SMMU_CB_ATS1PR); if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp, !(tmp & ATSR_ACTIVE), 5, 50)) { |