Commit ac3c4563 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

Merge tag 'arm-smmu-updates' of...

Merge tag 'arm-smmu-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into arm/smmu

Arm SMMU updates for 6.5

- Device-tree binding updates:
  * Add missing clocks for SC8280XP and SA8775 Adreno SMMUs
  * Add two new Qualcomm SMMUs in SDX75 and SM6375

- Workarounds for Arm MMU-700 errata:
  * 1076982: Avoid use of SEV-based cmdq wakeup
  * 2812531: Terminate command batches with a CMD_SYNC
  * Enforce single-stage translation to avoid nesting-related errata

- Set the correct level hint for range TLB invalidation on teardown
parents 44c026a7 c5fb66a1
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -140,6 +140,10 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | MMU-500         | #841119,826419  | N/A                         |
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | MMU-600         | #1076982,1209401| N/A                         |
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | MMU-700         | #2268618,2812531| N/A                         |
+----------------+-----------------+-----------------+-----------------------------+
+----------------+-----------------+-----------------+-----------------------------+
| Broadcom       | Brahma-B53      | N/A             | ARM64_ERRATUM_845719        |
+----------------+-----------------+-----------------+-----------------------------+
+9 −3
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ properties:
              - qcom,msm8996-smmu-v2
              - qcom,msm8998-smmu-v2
              - qcom,sdm630-smmu-v2
              - qcom,sm6375-smmu-v2
          - const: qcom,smmu-v2

      - description: Qcom SoCs implementing "qcom,smmu-500" and "arm,mmu-500"
@@ -45,6 +46,7 @@ properties:
              - qcom,sdm845-smmu-500
              - qcom,sdx55-smmu-500
              - qcom,sdx65-smmu-500
              - qcom,sdx75-smmu-500
              - qcom,sm6115-smmu-500
              - qcom,sm6125-smmu-500
              - qcom,sm6350-smmu-500
@@ -79,7 +81,9 @@ properties:
      - description: Qcom Adreno GPUs implementing "qcom,smmu-500" and "arm,mmu-500"
        items:
          - enum:
              - qcom,sa8775p-smmu-500
              - qcom,sc7280-smmu-500
              - qcom,sc8280xp-smmu-500
              - qcom,sm6115-smmu-500
              - qcom,sm6125-smmu-500
              - qcom,sm8150-smmu-500
@@ -267,6 +271,7 @@ allOf:
            enum:
              - qcom,msm8998-smmu-v2
              - qcom,sdm630-smmu-v2
              - qcom,sm6375-smmu-v2
    then:
      anyOf:
        - properties:
@@ -331,7 +336,10 @@ allOf:
      properties:
        compatible:
          contains:
            const: qcom,sc7280-smmu-500
            enum:
              - qcom,sa8775p-smmu-500
              - qcom,sc7280-smmu-500
              - qcom,sc8280xp-smmu-500
    then:
      properties:
        clock-names:
@@ -413,10 +421,8 @@ allOf:
              - nvidia,smmu-500
              - qcom,qcm2290-smmu-500
              - qcom,qdu1000-smmu-500
              - qcom,sa8775p-smmu-500
              - qcom,sc7180-smmu-500
              - qcom,sc8180x-smmu-500
              - qcom,sc8280xp-smmu-500
              - qcom,sdm670-smmu-500
              - qcom,sdm845-smmu-500
              - qcom,sdx55-smmu-500
+57 −2
Original line number Diff line number Diff line
@@ -894,6 +894,12 @@ static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu,
{
	int index;

	if (cmds->num == CMDQ_BATCH_ENTRIES - 1 &&
	    (smmu->options & ARM_SMMU_OPT_CMDQ_FORCE_SYNC)) {
		arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, true);
		cmds->num = 0;
	}

	if (cmds->num == CMDQ_BATCH_ENTRIES) {
		arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, false);
		cmds->num = 0;
@@ -1892,7 +1898,12 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
		/* Convert page size of 12,14,16 (log2) to 1,2,3 */
		cmd->tlbi.tg = (tg - 10) / 2;

		/* Determine what level the granule is at */
		/*
		 * Determine what level the granule is at. For non-leaf, io-pgtable
		 * assumes .tlb_flush_walk can invalidate multiple levels at once,
		 * so ignore the nominal last-level granule and leave TTL=0.
		 */
		if (cmd->tlbi.leaf)
			cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3));

		num_pages = size >> tg;
@@ -3429,6 +3440,44 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
	return 0;
}

#define IIDR_IMPLEMENTER_ARM		0x43b
#define IIDR_PRODUCTID_ARM_MMU_600	0x483
#define IIDR_PRODUCTID_ARM_MMU_700	0x487

static void arm_smmu_device_iidr_probe(struct arm_smmu_device *smmu)
{
	u32 reg;
	unsigned int implementer, productid, variant, revision;

	reg = readl_relaxed(smmu->base + ARM_SMMU_IIDR);
	implementer = FIELD_GET(IIDR_IMPLEMENTER, reg);
	productid = FIELD_GET(IIDR_PRODUCTID, reg);
	variant = FIELD_GET(IIDR_VARIANT, reg);
	revision = FIELD_GET(IIDR_REVISION, reg);

	switch (implementer) {
	case IIDR_IMPLEMENTER_ARM:
		switch (productid) {
		case IIDR_PRODUCTID_ARM_MMU_600:
			/* Arm erratum 1076982 */
			if (variant == 0 && revision <= 2)
				smmu->features &= ~ARM_SMMU_FEAT_SEV;
			/* Arm erratum 1209401 */
			if (variant < 2)
				smmu->features &= ~ARM_SMMU_FEAT_NESTING;
			break;
		case IIDR_PRODUCTID_ARM_MMU_700:
			/* Arm erratum 2812531 */
			smmu->features &= ~ARM_SMMU_FEAT_BTM;
			smmu->options |= ARM_SMMU_OPT_CMDQ_FORCE_SYNC;
			/* Arm errata 2268618, 2812531 */
			smmu->features &= ~ARM_SMMU_FEAT_NESTING;
			break;
		}
		break;
	}
}

static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
{
	u32 reg;
@@ -3635,6 +3684,12 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)

	smmu->ias = max(smmu->ias, smmu->oas);

	if ((smmu->features & ARM_SMMU_FEAT_TRANS_S1) &&
	    (smmu->features & ARM_SMMU_FEAT_TRANS_S2))
		smmu->features |= ARM_SMMU_FEAT_NESTING;

	arm_smmu_device_iidr_probe(smmu);

	if (arm_smmu_sva_supported(smmu))
		smmu->features |= ARM_SMMU_FEAT_SVA;

+8 −0
Original line number Diff line number Diff line
@@ -69,6 +69,12 @@
#define IDR5_VAX			GENMASK(11, 10)
#define IDR5_VAX_52_BIT			1

#define ARM_SMMU_IIDR			0x18
#define IIDR_PRODUCTID			GENMASK(31, 20)
#define IIDR_VARIANT			GENMASK(19, 16)
#define IIDR_REVISION			GENMASK(15, 12)
#define IIDR_IMPLEMENTER		GENMASK(11, 0)

#define ARM_SMMU_CR0			0x20
#define CR0_ATSCHK			(1 << 4)
#define CR0_CMDQEN			(1 << 3)
@@ -639,11 +645,13 @@ struct arm_smmu_device {
#define ARM_SMMU_FEAT_BTM		(1 << 16)
#define ARM_SMMU_FEAT_SVA		(1 << 17)
#define ARM_SMMU_FEAT_E2H		(1 << 18)
#define ARM_SMMU_FEAT_NESTING		(1 << 19)
	u32				features;

#define ARM_SMMU_OPT_SKIP_PREFETCH	(1 << 0)
#define ARM_SMMU_OPT_PAGE0_REGS_ONLY	(1 << 1)
#define ARM_SMMU_OPT_MSIPOLL		(1 << 2)
#define ARM_SMMU_OPT_CMDQ_FORCE_SYNC	(1 << 3)
	u32				options;

	struct arm_smmu_cmdq		cmdq;