Commit df457ca9 authored by Robin Murphy's avatar Robin Murphy Committed by Will Deacon
Browse files

perf/smmuv3: Synthesize IIDR from CoreSight ID registers



The SMMU_PMCG_IIDR register was not present in older revisions of the
Arm SMMUv3 spec. On Arm Ltd. implementations, the IIDR value consists of
fields from several PIDR registers, allowing us to present a
standardized identifier to userspace.

Signed-off-by: default avatarRobin Murphy <robin.murphy@arm.com>
Signed-off-by: default avatarJean-Philippe Brucker <jean-philippe@linaro.org>
Link: https://lore.kernel.org/r/20211117144844.241072-4-jean-philippe@linaro.org


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 3f7be435
Loading
Loading
Loading
Loading
+54 −1
Original line number Diff line number Diff line
@@ -76,6 +76,10 @@
#define SMMU_PMCG_CR                    0xE04
#define SMMU_PMCG_CR_ENABLE             BIT(0)
#define SMMU_PMCG_IIDR                  0xE08
#define SMMU_PMCG_IIDR_PRODUCTID        GENMASK(31, 20)
#define SMMU_PMCG_IIDR_VARIANT          GENMASK(19, 16)
#define SMMU_PMCG_IIDR_REVISION         GENMASK(15, 12)
#define SMMU_PMCG_IIDR_IMPLEMENTER      GENMASK(11, 0)
#define SMMU_PMCG_CEID0                 0xE20
#define SMMU_PMCG_CEID1                 0xE28
#define SMMU_PMCG_IRQ_CTRL              0xE50
@@ -84,6 +88,20 @@
#define SMMU_PMCG_IRQ_CFG1              0xE60
#define SMMU_PMCG_IRQ_CFG2              0xE64

/* IMP-DEF ID registers */
#define SMMU_PMCG_PIDR0                 0xFE0
#define SMMU_PMCG_PIDR0_PART_0          GENMASK(7, 0)
#define SMMU_PMCG_PIDR1                 0xFE4
#define SMMU_PMCG_PIDR1_DES_0           GENMASK(7, 4)
#define SMMU_PMCG_PIDR1_PART_1          GENMASK(3, 0)
#define SMMU_PMCG_PIDR2                 0xFE8
#define SMMU_PMCG_PIDR2_REVISION        GENMASK(7, 4)
#define SMMU_PMCG_PIDR2_DES_1           GENMASK(2, 0)
#define SMMU_PMCG_PIDR3                 0xFEC
#define SMMU_PMCG_PIDR3_REVAND          GENMASK(7, 4)
#define SMMU_PMCG_PIDR4                 0xFD0
#define SMMU_PMCG_PIDR4_DES_2           GENMASK(3, 0)

/* MSI config fields */
#define MSI_CFG0_ADDR_MASK              GENMASK_ULL(51, 2)
#define MSI_CFG2_MEMATTR_DEVICE_nGnRE   0x1
@@ -755,6 +773,41 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu)
	dev_notice(smmu_pmu->dev, "option mask 0x%x\n", smmu_pmu->options);
}

static bool smmu_pmu_coresight_id_regs(struct smmu_pmu *smmu_pmu)
{
	return of_device_is_compatible(smmu_pmu->dev->of_node,
				       "arm,mmu-600-pmcg");
}

static void smmu_pmu_get_iidr(struct smmu_pmu *smmu_pmu)
{
	u32 iidr = readl_relaxed(smmu_pmu->reg_base + SMMU_PMCG_IIDR);

	if (!iidr && smmu_pmu_coresight_id_regs(smmu_pmu)) {
		u32 pidr0 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR0);
		u32 pidr1 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR1);
		u32 pidr2 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR2);
		u32 pidr3 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR3);
		u32 pidr4 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR4);

		u32 productid = FIELD_GET(SMMU_PMCG_PIDR0_PART_0, pidr0) |
				(FIELD_GET(SMMU_PMCG_PIDR1_PART_1, pidr1) << 8);
		u32 variant = FIELD_GET(SMMU_PMCG_PIDR2_REVISION, pidr2);
		u32 revision = FIELD_GET(SMMU_PMCG_PIDR3_REVAND, pidr3);
		u32 implementer =
			FIELD_GET(SMMU_PMCG_PIDR1_DES_0, pidr1) |
			(FIELD_GET(SMMU_PMCG_PIDR2_DES_1, pidr2) << 4) |
			(FIELD_GET(SMMU_PMCG_PIDR4_DES_2, pidr4) << 8);

		iidr = FIELD_PREP(SMMU_PMCG_IIDR_PRODUCTID, productid) |
		       FIELD_PREP(SMMU_PMCG_IIDR_VARIANT, variant) |
		       FIELD_PREP(SMMU_PMCG_IIDR_REVISION, revision) |
		       FIELD_PREP(SMMU_PMCG_IIDR_IMPLEMENTER, implementer);
	}

	smmu_pmu->iidr = iidr;
}

static int smmu_pmu_probe(struct platform_device *pdev)
{
	struct smmu_pmu *smmu_pmu;
@@ -826,7 +879,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
		return err;
	}

	smmu_pmu->iidr = readl_relaxed(smmu_pmu->reg_base + SMMU_PMCG_IIDR);
	smmu_pmu_get_iidr(smmu_pmu);

	name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "smmuv3_pmcg_%llx",
			      (res_0->start) >> SMMU_PMCG_PA_SHIFT);