Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8cd0b952 authored by Mitchel Humpherys's avatar Mitchel Humpherys Committed by Matt Wagantall
Browse files

iommu/arm-smmu: add DT option to skip certain initialization



On some targets, context banks can be dedicated for use by other
execution environments outside of Linux.  However, we currently assume
that we own all of the context banks during SMMU initialization in
arm_smmu_device_reset.  This can mess up the other execution
environments since we are trampling on their SCTLR, SMR, and S2CR.
Provide a DT option to skip this initialization altogether, since the
other execution environment should have already initialized the SMMU
anyways.

Change-Id: I0ed4cbbcdad596f9201f83cb7d0e28a289e18a6e
Signed-off-by: default avatarMitchel Humpherys <mitchelh@codeaurora.org>
parent 593292df
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -62,6 +62,14 @@ conditions.
                  driver to assume that configuration registers will retain
                  their values across gdsc power gating.

- qcom,skip-init : Disable resetting configuration for all context banks
                  during device reset.  This is useful for targets where
                  some context banks are dedicated to other execution
                  environments outside of Linux and those other EEs are
                  programming their own stream match tables, SCTLR, etc.
                  Without setting this option we will trample on their
                  configuration.

- 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
+16 −11
Original line number Diff line number Diff line
@@ -422,6 +422,7 @@ struct arm_smmu_device {
#define ARM_SMMU_OPT_INVALIDATE_ON_MAP (1 << 1)
#define ARM_SMMU_OPT_HALT_AND_TLB_ON_ATOS  (1 << 2)
#define ARM_SMMU_OPT_REGISTER_SAVE	(1 << 3)
#define ARM_SMMU_OPT_SKIP_INIT		(1 << 4)
	u32				options;
	enum arm_smmu_arch_version	version;

@@ -490,6 +491,7 @@ static struct arm_smmu_option_prop arm_smmu_options[] = {
	{ ARM_SMMU_OPT_INVALIDATE_ON_MAP, "qcom,smmu-invalidate-on-map" },
	{ ARM_SMMU_OPT_HALT_AND_TLB_ON_ATOS, "qcom,halt-and-tlb-on-atos" },
	{ ARM_SMMU_OPT_REGISTER_SAVE, "qcom,register-save" },
	{ ARM_SMMU_OPT_SKIP_INIT, "qcom,skip-init" },
	{ 0, NULL},
};

@@ -2127,9 +2129,11 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
	reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
	writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);

	if (!(smmu->options & ARM_SMMU_OPT_SKIP_INIT)) {
		/* Mark all SMRn as invalid and all S2CRn as bypass */
		for (i = 0; i < smmu->num_mapping_groups; ++i) {
		writel_relaxed(0, gr0_base + ARM_SMMU_GR0_SMR(i));
			writel_relaxed(0,
				gr0_base + ARM_SMMU_GR0_SMR(i));
			writel_relaxed(S2CR_TYPE_BYPASS,
				gr0_base + ARM_SMMU_GR0_S2CR(i));
		}
@@ -2140,6 +2144,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
			writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
			writel_relaxed(FSR_FAULT, cb_base + ARM_SMMU_CB_FSR);
		}
	}

	/* Invalidate the TLB, just in case */
	writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH);