aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Herrmann <andreas.herrmann@calxeda.com>2013-10-01 08:39:09 -0400
committerWill Deacon <will.deacon@arm.com>2013-10-09 09:14:41 -0400
commit659db6f6beacae6fe49b5566debc4e82f678ff63 (patch)
tree76f38b1f4dc8da72d9f289fa28f46404f13e52e1
parent2ef0f03120ea2ad64d0e70f032a58e6c13603cdc (diff)
iommu/arm-smmu: Clear global and context bank fault status registers
After reset these registers have unknown values. This might cause problems when evaluating SMMU_GFSR and/or SMMU_CB_FSR in handlers for combined interrupts. Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--drivers/iommu/arm-smmu.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index a984e08eb084..0f45a489ccf9 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1562,9 +1562,13 @@ static struct iommu_ops arm_smmu_ops = {
1562static void arm_smmu_device_reset(struct arm_smmu_device *smmu) 1562static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
1563{ 1563{
1564 void __iomem *gr0_base = ARM_SMMU_GR0(smmu); 1564 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1565 void __iomem *sctlr_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB_SCTLR; 1565 void __iomem *cb_base;
1566 int i = 0; 1566 int i = 0;
1567 u32 scr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0); 1567 u32 reg;
1568
1569 /* Clear Global FSR */
1570 reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR);
1571 writel(reg, gr0_base + ARM_SMMU_GR0_sGFSR);
1568 1572
1569 /* Mark all SMRn as invalid and all S2CRn as bypass */ 1573 /* Mark all SMRn as invalid and all S2CRn as bypass */
1570 for (i = 0; i < smmu->num_mapping_groups; ++i) { 1574 for (i = 0; i < smmu->num_mapping_groups; ++i) {
@@ -1572,33 +1576,38 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
1572 writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i)); 1576 writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i));
1573 } 1577 }
1574 1578
1575 /* Make sure all context banks are disabled */ 1579 /* Make sure all context banks are disabled and clear CB_FSR */
1576 for (i = 0; i < smmu->num_context_banks; ++i) 1580 for (i = 0; i < smmu->num_context_banks; ++i) {
1577 writel_relaxed(0, sctlr_base + ARM_SMMU_CB(smmu, i)); 1581 cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);
1582 writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
1583 writel_relaxed(FSR_FAULT, cb_base + ARM_SMMU_CB_FSR);
1584 }
1578 1585
1579 /* Invalidate the TLB, just in case */ 1586 /* Invalidate the TLB, just in case */
1580 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_STLBIALL); 1587 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_STLBIALL);
1581 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH); 1588 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH);
1582 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH); 1589 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH);
1583 1590
1591 reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0);
1592
1584 /* Enable fault reporting */ 1593 /* Enable fault reporting */
1585 scr0 |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE); 1594 reg |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE);
1586 1595
1587 /* Disable TLB broadcasting. */ 1596 /* Disable TLB broadcasting. */
1588 scr0 |= (sCR0_VMIDPNE | sCR0_PTM); 1597 reg |= (sCR0_VMIDPNE | sCR0_PTM);
1589 1598
1590 /* Enable client access, but bypass when no mapping is found */ 1599 /* Enable client access, but bypass when no mapping is found */
1591 scr0 &= ~(sCR0_CLIENTPD | sCR0_USFCFG); 1600 reg &= ~(sCR0_CLIENTPD | sCR0_USFCFG);
1592 1601
1593 /* Disable forced broadcasting */ 1602 /* Disable forced broadcasting */
1594 scr0 &= ~sCR0_FB; 1603 reg &= ~sCR0_FB;
1595 1604
1596 /* Don't upgrade barriers */ 1605 /* Don't upgrade barriers */
1597 scr0 &= ~(sCR0_BSU_MASK << sCR0_BSU_SHIFT); 1606 reg &= ~(sCR0_BSU_MASK << sCR0_BSU_SHIFT);
1598 1607
1599 /* Push the button */ 1608 /* Push the button */
1600 arm_smmu_tlb_sync(smmu); 1609 arm_smmu_tlb_sync(smmu);
1601 writel_relaxed(scr0, gr0_base + ARM_SMMU_GR0_sCR0); 1610 writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sCR0);
1602} 1611}
1603 1612
1604static int arm_smmu_id_size_to_bits(int size) 1613static int arm_smmu_id_size_to_bits(int size)