aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/arm-smmu.c
diff options
context:
space:
mode:
authorAndreas Herrmann <andreas.herrmann@calxeda.com>2014-01-30 13:18:04 -0500
committerWill Deacon <will.deacon@arm.com>2014-02-24 14:09:44 -0500
commit3a5df8ff35a28bfc0a3662a5906af2c98d4807d8 (patch)
tree5ee8aa7ce853b56bae7561c71dc2f45cc12c6c68 /drivers/iommu/arm-smmu.c
parent636e97b0fb0a063dc89773b13064647f5da632cb (diff)
iommu/arm-smmu: support buggy implementations with secure cfg accesses
In such a case we have to use secure aliases of some non-secure registers. This handling is switched on by DT property "calxeda,smmu-secure-config-access" for an SMMU node. Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com> [will: merged with driver option handling patch] Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r--drivers/iommu/arm-smmu.c58
1 files changed, 48 insertions, 10 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index a3ce60887efa..e04fdcb4b9ba 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -60,6 +60,16 @@
60#define ARM_SMMU_GR0(smmu) ((smmu)->base) 60#define ARM_SMMU_GR0(smmu) ((smmu)->base)
61#define ARM_SMMU_GR1(smmu) ((smmu)->base + (smmu)->pagesize) 61#define ARM_SMMU_GR1(smmu) ((smmu)->base + (smmu)->pagesize)
62 62
63/*
64 * SMMU global address space with conditional offset to access secure
65 * aliases of non-secure registers (e.g. nsCR0: 0x400, nsGFSR: 0x448,
66 * nsGFSYNR0: 0x450)
67 */
68#define ARM_SMMU_GR0_NS(smmu) \
69 ((smmu)->base + \
70 ((smmu->options & ARM_SMMU_OPT_SECURE_CFG_ACCESS) \
71 ? 0x400 : 0))
72
63/* Page table bits */ 73/* Page table bits */
64#define ARM_SMMU_PTE_XN (((pteval_t)3) << 53) 74#define ARM_SMMU_PTE_XN (((pteval_t)3) << 53)
65#define ARM_SMMU_PTE_CONT (((pteval_t)1) << 52) 75#define ARM_SMMU_PTE_CONT (((pteval_t)1) << 52)
@@ -351,6 +361,9 @@ struct arm_smmu_device {
351#define ARM_SMMU_FEAT_TRANS_S2 (1 << 3) 361#define ARM_SMMU_FEAT_TRANS_S2 (1 << 3)
352#define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4) 362#define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4)
353 u32 features; 363 u32 features;
364
365#define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
366 u32 options;
354 int version; 367 int version;
355 368
356 u32 num_context_banks; 369 u32 num_context_banks;
@@ -401,6 +414,29 @@ struct arm_smmu_domain {
401static DEFINE_SPINLOCK(arm_smmu_devices_lock); 414static DEFINE_SPINLOCK(arm_smmu_devices_lock);
402static LIST_HEAD(arm_smmu_devices); 415static LIST_HEAD(arm_smmu_devices);
403 416
417struct arm_smmu_option_prop {
418 u32 opt;
419 const char *prop;
420};
421
422static struct arm_smmu_option_prop arm_smmu_options [] = {
423 { ARM_SMMU_OPT_SECURE_CFG_ACCESS, "calxeda,smmu-secure-config-access" },
424 { 0, NULL},
425};
426
427static void parse_driver_options(struct arm_smmu_device *smmu)
428{
429 int i = 0;
430 do {
431 if (of_property_read_bool(smmu->dev->of_node,
432 arm_smmu_options[i].prop)) {
433 smmu->options |= arm_smmu_options[i].opt;
434 dev_notice(smmu->dev, "option %s\n",
435 arm_smmu_options[i].prop);
436 }
437 } while (arm_smmu_options[++i].opt);
438}
439
404static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, 440static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu,
405 struct device_node *dev_node) 441 struct device_node *dev_node)
406{ 442{
@@ -614,16 +650,16 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
614{ 650{
615 u32 gfsr, gfsynr0, gfsynr1, gfsynr2; 651 u32 gfsr, gfsynr0, gfsynr1, gfsynr2;
616 struct arm_smmu_device *smmu = dev; 652 struct arm_smmu_device *smmu = dev;
617 void __iomem *gr0_base = ARM_SMMU_GR0(smmu); 653 void __iomem *gr0_base = ARM_SMMU_GR0_NS(smmu);
618 654
619 gfsr = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR); 655 gfsr = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR);
620 if (!gfsr)
621 return IRQ_NONE;
622
623 gfsynr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR0); 656 gfsynr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR0);
624 gfsynr1 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR1); 657 gfsynr1 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR1);
625 gfsynr2 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR2); 658 gfsynr2 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR2);
626 659
660 if (!gfsr)
661 return IRQ_NONE;
662
627 dev_err_ratelimited(smmu->dev, 663 dev_err_ratelimited(smmu->dev,
628 "Unexpected global fault, this could be serious\n"); 664 "Unexpected global fault, this could be serious\n");
629 dev_err_ratelimited(smmu->dev, 665 dev_err_ratelimited(smmu->dev,
@@ -1597,9 +1633,9 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
1597 int i = 0; 1633 int i = 0;
1598 u32 reg; 1634 u32 reg;
1599 1635
1600 /* Clear Global FSR */ 1636 /* clear global FSR */
1601 reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR); 1637 reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
1602 writel(reg, gr0_base + ARM_SMMU_GR0_sGFSR); 1638 writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
1603 1639
1604 /* Mark all SMRn as invalid and all S2CRn as bypass */ 1640 /* Mark all SMRn as invalid and all S2CRn as bypass */
1605 for (i = 0; i < smmu->num_mapping_groups; ++i) { 1641 for (i = 0; i < smmu->num_mapping_groups; ++i) {
@@ -1619,7 +1655,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
1619 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH); 1655 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH);
1620 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH); 1656 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH);
1621 1657
1622 reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0); 1658 reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
1623 1659
1624 /* Enable fault reporting */ 1660 /* Enable fault reporting */
1625 reg |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE); 1661 reg |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE);
@@ -1638,7 +1674,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
1638 1674
1639 /* Push the button */ 1675 /* Push the button */
1640 arm_smmu_tlb_sync(smmu); 1676 arm_smmu_tlb_sync(smmu);
1641 writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sCR0); 1677 writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
1642} 1678}
1643 1679
1644static int arm_smmu_id_size_to_bits(int size) 1680static int arm_smmu_id_size_to_bits(int size)
@@ -1885,6 +1921,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
1885 if (err) 1921 if (err)
1886 goto out_put_parent; 1922 goto out_put_parent;
1887 1923
1924 parse_driver_options(smmu);
1925
1888 if (smmu->version > 1 && 1926 if (smmu->version > 1 &&
1889 smmu->num_context_banks != smmu->num_context_irqs) { 1927 smmu->num_context_banks != smmu->num_context_irqs) {
1890 dev_err(dev, 1928 dev_err(dev,
@@ -1969,7 +2007,7 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
1969 free_irq(smmu->irqs[i], smmu); 2007 free_irq(smmu->irqs[i], smmu);
1970 2008
1971 /* Turn the thing off */ 2009 /* Turn the thing off */
1972 writel_relaxed(sCR0_CLIENTPD, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_sCR0); 2010 writel(sCR0_CLIENTPD,ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
1973 return 0; 2011 return 0;
1974} 2012}
1975 2013