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 <pdhaval@codeaurora.org>
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
This commit is contained in:
Dhaval Patel 2015-05-09 14:47:29 -07:00 committed by David Keitel
parent b854c94f3d
commit 240d67c2b0
2 changed files with 25 additions and 13 deletions

View file

@ -104,6 +104,14 @@ conditions.
enabled for stage 1 translation" (Section 2.1: "Overview enabled for stage 1 translation" (Section 2.1: "Overview
of SMMU operation"). 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 - clocks : List of clocks to be used during SMMU register access. See
Documentation/devicetree/bindings/clock/clock-bindings.txt Documentation/devicetree/bindings/clock/clock-bindings.txt
for information about the format. For each clock specified for information about the format. For each clock specified

View file

@ -434,6 +434,7 @@ struct arm_smmu_device {
#define ARM_SMMU_OPT_FATAL_ASF (1 << 6) #define ARM_SMMU_OPT_FATAL_ASF (1 << 6)
#define ARM_SMMU_OPT_ERRATA_TZ_ATOS (1 << 7) #define ARM_SMMU_OPT_ERRATA_TZ_ATOS (1 << 7)
#define ARM_SMMU_OPT_NO_M (1 << 8) #define ARM_SMMU_OPT_NO_M (1 << 8)
#define ARM_SMMU_OPT_NO_SMR_CHECK (1 << 9)
u32 options; u32 options;
enum arm_smmu_arch_version version; 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_FATAL_ASF, "qcom,fatal-asf" },
{ ARM_SMMU_OPT_ERRATA_TZ_ATOS, "qcom,errata-tz-atos" }, { ARM_SMMU_OPT_ERRATA_TZ_ATOS, "qcom,errata-tz-atos" },
{ ARM_SMMU_OPT_NO_M, "qcom,no-mmu-enable" }, { ARM_SMMU_OPT_NO_M, "qcom,no-mmu-enable" },
{ ARM_SMMU_OPT_NO_SMR_CHECK, "qcom,no-smr-check" },
{ 0, NULL}, { 0, NULL},
}; };
@ -2517,18 +2519,20 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
return -ENODEV; return -ENODEV;
} }
smr = SMR_MASK_MASK << SMR_MASK_SHIFT; if (!(smmu->options & ARM_SMMU_OPT_NO_SMR_CHECK)) {
smr |= (SMR_ID_MASK << SMR_ID_SHIFT); smr = SMR_MASK_MASK << SMR_MASK_SHIFT;
writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0)); smr |= (SMR_ID_MASK << SMR_ID_SHIFT);
smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0)); 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; mask = (smr >> SMR_MASK_SHIFT) & SMR_MASK_MASK;
sid = (smr >> SMR_ID_SHIFT) & SMR_ID_MASK; sid = (smr >> SMR_ID_SHIFT) & SMR_ID_MASK;
if ((mask & sid) != sid) { if ((mask & sid) != sid) {
dev_err(smmu->dev, dev_err(smmu->dev,
"SMR mask bits (0x%x) insufficient for ID field (0x%x)\n", "SMR mask bits (0x%x) insufficient for ID field (0x%x)\n",
mask, sid); mask, sid);
return -ENODEV; return -ENODEV;
}
} }
dev_notice(smmu->dev, dev_notice(smmu->dev,
@ -2710,6 +2714,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
if (err) if (err)
goto out_put_masters; goto out_put_masters;
parse_driver_options(smmu);
arm_smmu_enable_regulators(smmu); arm_smmu_enable_regulators(smmu);
arm_smmu_enable_clocks(smmu); arm_smmu_enable_clocks(smmu);
err = arm_smmu_device_cfg_probe(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) if (err)
goto out_put_masters; goto out_put_masters;
parse_driver_options(smmu);
if (of_device_is_compatible(dev->of_node, "qcom,smmu-v2")) if (of_device_is_compatible(dev->of_node, "qcom,smmu-v2"))
smmu->model = SMMU_MODEL_QCOM_V2; smmu->model = SMMU_MODEL_QCOM_V2;