mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 15:39:42 -04:00
perf/arm_cspmu: Add pmpidr support
The PMIIDR value is composed by the values in PMPIDR registers. We can use PMPIDR registers as alternative for device identification for systems that do not implement PMIIDR. Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com> Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com> Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
committed by
Will Deacon
parent
a2573bc790
commit
04330be8dc
@@ -322,14 +322,14 @@ static struct arm_cspmu_impl_match impl_match[] = {
|
||||
{
|
||||
.module_name = "nvidia_cspmu",
|
||||
.pmiidr_val = ARM_CSPMU_IMPL_ID_NVIDIA,
|
||||
.pmiidr_mask = ARM_CSPMU_PMIIDR_IMPLEMENTER,
|
||||
.pmiidr_mask = PMIIDR_IMPLEMENTER,
|
||||
.module = NULL,
|
||||
.impl_init_ops = NULL,
|
||||
},
|
||||
{
|
||||
.module_name = "ampere_cspmu",
|
||||
.pmiidr_val = ARM_CSPMU_IMPL_ID_AMPERE,
|
||||
.pmiidr_mask = ARM_CSPMU_PMIIDR_IMPLEMENTER,
|
||||
.pmiidr_mask = PMIIDR_IMPLEMENTER,
|
||||
.module = NULL,
|
||||
.impl_init_ops = NULL,
|
||||
},
|
||||
@@ -351,6 +351,44 @@ static struct arm_cspmu_impl_match *arm_cspmu_impl_match_get(u32 pmiidr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static u32 arm_cspmu_get_pmiidr(struct arm_cspmu *cspmu)
|
||||
{
|
||||
u32 pmiidr, pmpidr;
|
||||
|
||||
pmiidr = readl(cspmu->base0 + PMIIDR);
|
||||
|
||||
if (pmiidr != 0)
|
||||
return pmiidr;
|
||||
|
||||
/* Construct PMIIDR value from PMPIDRs. */
|
||||
|
||||
pmpidr = readl(cspmu->base0 + PMPIDR0);
|
||||
pmiidr |= FIELD_PREP(PMIIDR_PRODUCTID_PART_0,
|
||||
FIELD_GET(PMPIDR0_PART_0, pmpidr));
|
||||
|
||||
pmpidr = readl(cspmu->base0 + PMPIDR1);
|
||||
pmiidr |= FIELD_PREP(PMIIDR_PRODUCTID_PART_1,
|
||||
FIELD_GET(PMPIDR1_PART_1, pmpidr));
|
||||
pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_0,
|
||||
FIELD_GET(PMPIDR1_DES_0, pmpidr));
|
||||
|
||||
pmpidr = readl(cspmu->base0 + PMPIDR2);
|
||||
pmiidr |= FIELD_PREP(PMIIDR_VARIANT,
|
||||
FIELD_GET(PMPIDR2_REVISION, pmpidr));
|
||||
pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_1,
|
||||
FIELD_GET(PMPIDR2_DES_1, pmpidr));
|
||||
|
||||
pmpidr = readl(cspmu->base0 + PMPIDR3);
|
||||
pmiidr |= FIELD_PREP(PMIIDR_REVISION,
|
||||
FIELD_GET(PMPIDR3_REVAND, pmpidr));
|
||||
|
||||
pmpidr = readl(cspmu->base0 + PMPIDR4);
|
||||
pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_2,
|
||||
FIELD_GET(PMPIDR4_DES_2, pmpidr));
|
||||
|
||||
return pmiidr;
|
||||
}
|
||||
|
||||
#define DEFAULT_IMPL_OP(name) .name = arm_cspmu_##name
|
||||
|
||||
static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
|
||||
@@ -361,7 +399,7 @@ static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
|
||||
|
||||
/* Start with a default PMU implementation */
|
||||
cspmu->impl.module = THIS_MODULE;
|
||||
cspmu->impl.pmiidr = readl(cspmu->base0 + PMIIDR);
|
||||
cspmu->impl.pmiidr = arm_cspmu_get_pmiidr(cspmu);
|
||||
cspmu->impl.ops = (struct arm_cspmu_impl_ops) {
|
||||
DEFAULT_IMPL_OP(get_event_attrs),
|
||||
DEFAULT_IMPL_OP(get_format_attrs),
|
||||
|
||||
@@ -86,6 +86,11 @@
|
||||
#define PMCFGR 0xE00
|
||||
#define PMCR 0xE04
|
||||
#define PMIIDR 0xE08
|
||||
#define PMPIDR0 0xFE0
|
||||
#define PMPIDR1 0xFE4
|
||||
#define PMPIDR2 0xFE8
|
||||
#define PMPIDR3 0xFEC
|
||||
#define PMPIDR4 0xFD0
|
||||
|
||||
/* PMCFGR register field */
|
||||
#define PMCFGR_NCG GENMASK(31, 28)
|
||||
@@ -115,8 +120,34 @@
|
||||
#define PMCR_E BIT(0)
|
||||
|
||||
/* PMIIDR register field */
|
||||
#define ARM_CSPMU_PMIIDR_IMPLEMENTER GENMASK(11, 0)
|
||||
#define ARM_CSPMU_PMIIDR_PRODUCTID GENMASK(31, 20)
|
||||
#define PMIIDR_IMPLEMENTER GENMASK(11, 0)
|
||||
#define PMIIDR_IMPLEMENTER_DES_0 GENMASK(3, 0)
|
||||
#define PMIIDR_IMPLEMENTER_DES_1 GENMASK(6, 4)
|
||||
#define PMIIDR_IMPLEMENTER_DES_2 GENMASK(11, 8)
|
||||
#define PMIIDR_REVISION GENMASK(15, 12)
|
||||
#define PMIIDR_VARIANT GENMASK(19, 16)
|
||||
#define PMIIDR_PRODUCTID GENMASK(31, 20)
|
||||
#define PMIIDR_PRODUCTID_PART_0 GENMASK(27, 20)
|
||||
#define PMIIDR_PRODUCTID_PART_1 GENMASK(31, 28)
|
||||
|
||||
/* PMPIDR0 register field */
|
||||
#define PMPIDR0_PART_0 GENMASK(7, 0)
|
||||
|
||||
/* PMPIDR1 register field */
|
||||
#define PMPIDR1_DES_0 GENMASK(7, 4)
|
||||
#define PMPIDR1_PART_1 GENMASK(3, 0)
|
||||
|
||||
/* PMPIDR2 register field */
|
||||
#define PMPIDR2_REVISION GENMASK(7, 4)
|
||||
#define PMPIDR2_DES_1 GENMASK(2, 0)
|
||||
|
||||
/* PMPIDR3 register field */
|
||||
#define PMPIDR3_REVAND GENMASK(7, 4)
|
||||
#define PMPIDR3_CMOD GENMASK(3, 0)
|
||||
|
||||
/* PMPIDR4 register field */
|
||||
#define PMPIDR4_SIZE GENMASK(7, 4)
|
||||
#define PMPIDR4_DES_2 GENMASK(3, 0)
|
||||
|
||||
/* JEDEC-assigned JEP106 identification code */
|
||||
#define ARM_CSPMU_IMPL_ID_NVIDIA 0x36B
|
||||
|
||||
@@ -322,7 +322,7 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
prodid = FIELD_GET(ARM_CSPMU_PMIIDR_PRODUCTID, cspmu->impl.pmiidr);
|
||||
prodid = FIELD_GET(PMIIDR_PRODUCTID, cspmu->impl.pmiidr);
|
||||
|
||||
/* Find matching PMU. */
|
||||
for (; match->prodid; match++) {
|
||||
|
||||
Reference in New Issue
Block a user