diff options
author | Andreas Herrmann <andreas.herrmann@calxeda.com> | 2013-10-01 08:39:09 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2013-10-09 09:14:41 -0400 |
commit | 659db6f6beacae6fe49b5566debc4e82f678ff63 (patch) | |
tree | 76f38b1f4dc8da72d9f289fa28f46404f13e52e1 | |
parent | 2ef0f03120ea2ad64d0e70f032a58e6c13603cdc (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.c | 31 |
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 = { | |||
1562 | static void arm_smmu_device_reset(struct arm_smmu_device *smmu) | 1562 | static 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 | ||
1604 | static int arm_smmu_id_size_to_bits(int size) | 1613 | static int arm_smmu_id_size_to_bits(int size) |