From 240d67c2b05d5e3e0e358d7c607b531b65eb8b51 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Sat, 9 May 2015 14:47:29 -0700 Subject: [PATCH] iommu/arm-smmu: add option to skip SMR mask sanity check Usually when an SMMU probes we do a sanity check on the SMR registers to make sure they can fully support all of the mask bits. This check can cause problems for use cases where the SMMU is already in use when the SMMU probes. For example, for continuous splash screen support, the stream matching table is programmed before control is even turned over to Linux. Add an option to skip this sanity check. Change-Id: I51a9231fcd8b73034f1a1ca69e4fbb7e632635fa Signed-off-by: Dhaval Patel Signed-off-by: Mitchel Humpherys --- .../devicetree/bindings/iommu/arm,smmu.txt | 8 +++++ drivers/iommu/arm-smmu.c | 30 +++++++++++-------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index e1aaeb4a355c..c55b5499fcfe 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -104,6 +104,14 @@ conditions. enabled for stage 1 translation" (Section 2.1: "Overview of SMMU operation"). +- qcom,no-smr-check : Usually when an SMMU probes we do a sanity check on + the SMR registers to make sure they can fully support all + of the mask bits. This check can cause problems for use + cases where the SMMU is already in use when the SMMU + probes. For example, for continuous splash screen + support, the stream matching table is programmed before + control is even turned over to Linux. + - clocks : List of clocks to be used during SMMU register access. See Documentation/devicetree/bindings/clock/clock-bindings.txt for information about the format. For each clock specified diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 507634c413a9..6cb08d5f8e8f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -434,6 +434,7 @@ struct arm_smmu_device { #define ARM_SMMU_OPT_FATAL_ASF (1 << 6) #define ARM_SMMU_OPT_ERRATA_TZ_ATOS (1 << 7) #define ARM_SMMU_OPT_NO_M (1 << 8) +#define ARM_SMMU_OPT_NO_SMR_CHECK (1 << 9) u32 options; enum arm_smmu_arch_version version; @@ -509,6 +510,7 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { ARM_SMMU_OPT_FATAL_ASF, "qcom,fatal-asf" }, { ARM_SMMU_OPT_ERRATA_TZ_ATOS, "qcom,errata-tz-atos" }, { ARM_SMMU_OPT_NO_M, "qcom,no-mmu-enable" }, + { ARM_SMMU_OPT_NO_SMR_CHECK, "qcom,no-smr-check" }, { 0, NULL}, }; @@ -2517,18 +2519,20 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) return -ENODEV; } - smr = SMR_MASK_MASK << SMR_MASK_SHIFT; - smr |= (SMR_ID_MASK << SMR_ID_SHIFT); - writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0)); - smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0)); + if (!(smmu->options & ARM_SMMU_OPT_NO_SMR_CHECK)) { + smr = SMR_MASK_MASK << SMR_MASK_SHIFT; + smr |= (SMR_ID_MASK << SMR_ID_SHIFT); + writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0)); + smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0)); - mask = (smr >> SMR_MASK_SHIFT) & SMR_MASK_MASK; - sid = (smr >> SMR_ID_SHIFT) & SMR_ID_MASK; - if ((mask & sid) != sid) { - dev_err(smmu->dev, - "SMR mask bits (0x%x) insufficient for ID field (0x%x)\n", - mask, sid); - return -ENODEV; + mask = (smr >> SMR_MASK_SHIFT) & SMR_MASK_MASK; + sid = (smr >> SMR_ID_SHIFT) & SMR_ID_MASK; + if ((mask & sid) != sid) { + dev_err(smmu->dev, + "SMR mask bits (0x%x) insufficient for ID field (0x%x)\n", + mask, sid); + return -ENODEV; + } } dev_notice(smmu->dev, @@ -2710,6 +2714,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) if (err) goto out_put_masters; + parse_driver_options(smmu); + arm_smmu_enable_regulators(smmu); arm_smmu_enable_clocks(smmu); err = arm_smmu_device_cfg_probe(smmu); @@ -2718,8 +2724,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) if (err) goto out_put_masters; - parse_driver_options(smmu); - if (of_device_is_compatible(dev->of_node, "qcom,smmu-v2")) smmu->model = SMMU_MODEL_QCOM_V2;