iommu/arm-smmu: Fix 16-bit ASID configuration
authorSunil Goutham <sgoutham@cavium.com>
Tue, 28 Mar 2017 10:41:12 +0000 (16:11 +0530)
committerWill Deacon <will.deacon@arm.com>
Thu, 6 Apr 2017 15:06:42 +0000 (16:06 +0100)
16-bit ASID should be enabled before initializing TTBR0/1,
otherwise only LSB 8-bit ASID will be considered. Hence
moving configuration of TTBCR register ahead of TTBR0/1
while initializing context bank.

Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
[will: rewrote comment]
Signed-off-by: Will Deacon <will.deacon@arm.com>
drivers/iommu/arm-smmu.c

index 8e16da64e72e00bf00c48943e7b140c4dbac519e..e021b360e3158c8ae497f655d8466f6aaa8a1dfe 100644 (file)
@@ -758,6 +758,29 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
        }
        writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
 
+       /*
+        * TTBCR
+        * We must write this before the TTBRs, since it determines the
+        * access behaviour of some fields (in particular, ASID[15:8]).
+        */
+       if (stage1) {
+               if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
+                       reg = pgtbl_cfg->arm_v7s_cfg.tcr;
+                       reg2 = 0;
+               } else {
+                       reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
+                       reg2 = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
+                       reg2 |= TTBCR2_SEP_UPSTREAM;
+                       if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
+                               reg2 |= TTBCR2_AS;
+               }
+               if (smmu->version > ARM_SMMU_V1)
+                       writel_relaxed(reg2, cb_base + ARM_SMMU_CB_TTBCR2);
+       } else {
+               reg = pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
+       }
+       writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
+
        /* TTBRs */
        if (stage1) {
                u16 asid = ARM_SMMU_CB_ASID(smmu, cfg);
@@ -781,25 +804,6 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
                writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR0);
        }
 
-       /* TTBCR */
-       if (stage1) {
-               if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
-                       reg = pgtbl_cfg->arm_v7s_cfg.tcr;
-                       reg2 = 0;
-               } else {
-                       reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
-                       reg2 = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
-                       reg2 |= TTBCR2_SEP_UPSTREAM;
-                       if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
-                               reg2 |= TTBCR2_AS;
-               }
-               if (smmu->version > ARM_SMMU_V1)
-                       writel_relaxed(reg2, cb_base + ARM_SMMU_CB_TTBCR2);
-       } else {
-               reg = pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
-       }
-       writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
-
        /* MAIRs (stage-1 only) */
        if (stage1) {
                if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {