aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2014-02-06 09:59:05 -0500
committerWill Deacon <will.deacon@arm.com>2014-02-10 12:02:23 -0500
commit57ca90f6800987ac274d7ba065ae6692cdf9bcd7 (patch)
tree8b7ddc5f80bc4eb6dce0a9131b3e184899cf730b
parent6dd35f45b8dac827b6f9dd86f5aca6436cdd2410 (diff)
iommu/arm-smmu: set CBARn.BPSHCFG to NSH for s1-s2-bypass contexts
Whilst trying to bring-up an SMMUv2 implementation with the table walker plumbed into a coherent interconnect, I noticed that the memory transactions targetting the CPU caches from the SMMU were marked as outer-shareable instead of inner-shareable. After a bunch of digging, it seems that we actually need to program CBARn.BPSHCFG for s1-s2-bypass contexts to act as non-shareable in order for the shareability configured in the corresponding TTBCR not to be overridden with an outer-shareable attribute. Cc: <stable@vger.kernel.org> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--drivers/iommu/arm-smmu.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 509f01f054d9..0ae4dd39197f 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -190,6 +190,9 @@
190#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) 190#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
191#define CBAR_VMID_SHIFT 0 191#define CBAR_VMID_SHIFT 0
192#define CBAR_VMID_MASK 0xff 192#define CBAR_VMID_MASK 0xff
193#define CBAR_S1_BPSHCFG_SHIFT 8
194#define CBAR_S1_BPSHCFG_MASK 3
195#define CBAR_S1_BPSHCFG_NSH 3
193#define CBAR_S1_MEMATTR_SHIFT 12 196#define CBAR_S1_MEMATTR_SHIFT 12
194#define CBAR_S1_MEMATTR_MASK 0xf 197#define CBAR_S1_MEMATTR_MASK 0xf
195#define CBAR_S1_MEMATTR_WB 0xf 198#define CBAR_S1_MEMATTR_WB 0xf
@@ -671,11 +674,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
671 if (smmu->version == 1) 674 if (smmu->version == 1)
672 reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT; 675 reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT;
673 676
674 /* Use the weakest memory type, so it is overridden by the pte */ 677 /*
675 if (stage1) 678 * Use the weakest shareability/memory types, so they are
676 reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); 679 * overridden by the ttbcr/pte.
677 else 680 */
681 if (stage1) {
682 reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
683 (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
684 } else {
678 reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT; 685 reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT;
686 }
679 writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx)); 687 writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx));
680 688
681 if (smmu->version > 1) { 689 if (smmu->version > 1) {