Skip to content

Commit 04330be

Browse files
bwicaksononvwilldeacon
authored andcommitted
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>
1 parent a2573bc commit 04330be

3 files changed

Lines changed: 75 additions & 6 deletions

File tree

drivers/perf/arm_cspmu/arm_cspmu.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,14 +322,14 @@ static struct arm_cspmu_impl_match impl_match[] = {
322322
{
323323
.module_name = "nvidia_cspmu",
324324
.pmiidr_val = ARM_CSPMU_IMPL_ID_NVIDIA,
325-
.pmiidr_mask = ARM_CSPMU_PMIIDR_IMPLEMENTER,
325+
.pmiidr_mask = PMIIDR_IMPLEMENTER,
326326
.module = NULL,
327327
.impl_init_ops = NULL,
328328
},
329329
{
330330
.module_name = "ampere_cspmu",
331331
.pmiidr_val = ARM_CSPMU_IMPL_ID_AMPERE,
332-
.pmiidr_mask = ARM_CSPMU_PMIIDR_IMPLEMENTER,
332+
.pmiidr_mask = PMIIDR_IMPLEMENTER,
333333
.module = NULL,
334334
.impl_init_ops = NULL,
335335
},
@@ -351,6 +351,44 @@ static struct arm_cspmu_impl_match *arm_cspmu_impl_match_get(u32 pmiidr)
351351
return NULL;
352352
}
353353

354+
static u32 arm_cspmu_get_pmiidr(struct arm_cspmu *cspmu)
355+
{
356+
u32 pmiidr, pmpidr;
357+
358+
pmiidr = readl(cspmu->base0 + PMIIDR);
359+
360+
if (pmiidr != 0)
361+
return pmiidr;
362+
363+
/* Construct PMIIDR value from PMPIDRs. */
364+
365+
pmpidr = readl(cspmu->base0 + PMPIDR0);
366+
pmiidr |= FIELD_PREP(PMIIDR_PRODUCTID_PART_0,
367+
FIELD_GET(PMPIDR0_PART_0, pmpidr));
368+
369+
pmpidr = readl(cspmu->base0 + PMPIDR1);
370+
pmiidr |= FIELD_PREP(PMIIDR_PRODUCTID_PART_1,
371+
FIELD_GET(PMPIDR1_PART_1, pmpidr));
372+
pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_0,
373+
FIELD_GET(PMPIDR1_DES_0, pmpidr));
374+
375+
pmpidr = readl(cspmu->base0 + PMPIDR2);
376+
pmiidr |= FIELD_PREP(PMIIDR_VARIANT,
377+
FIELD_GET(PMPIDR2_REVISION, pmpidr));
378+
pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_1,
379+
FIELD_GET(PMPIDR2_DES_1, pmpidr));
380+
381+
pmpidr = readl(cspmu->base0 + PMPIDR3);
382+
pmiidr |= FIELD_PREP(PMIIDR_REVISION,
383+
FIELD_GET(PMPIDR3_REVAND, pmpidr));
384+
385+
pmpidr = readl(cspmu->base0 + PMPIDR4);
386+
pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_2,
387+
FIELD_GET(PMPIDR4_DES_2, pmpidr));
388+
389+
return pmiidr;
390+
}
391+
354392
#define DEFAULT_IMPL_OP(name) .name = arm_cspmu_##name
355393

356394
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)
361399

362400
/* Start with a default PMU implementation */
363401
cspmu->impl.module = THIS_MODULE;
364-
cspmu->impl.pmiidr = readl(cspmu->base0 + PMIIDR);
402+
cspmu->impl.pmiidr = arm_cspmu_get_pmiidr(cspmu);
365403
cspmu->impl.ops = (struct arm_cspmu_impl_ops) {
366404
DEFAULT_IMPL_OP(get_event_attrs),
367405
DEFAULT_IMPL_OP(get_format_attrs),

drivers/perf/arm_cspmu/arm_cspmu.h

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@
8686
#define PMCFGR 0xE00
8787
#define PMCR 0xE04
8888
#define PMIIDR 0xE08
89+
#define PMPIDR0 0xFE0
90+
#define PMPIDR1 0xFE4
91+
#define PMPIDR2 0xFE8
92+
#define PMPIDR3 0xFEC
93+
#define PMPIDR4 0xFD0
8994

9095
/* PMCFGR register field */
9196
#define PMCFGR_NCG GENMASK(31, 28)
@@ -115,8 +120,34 @@
115120
#define PMCR_E BIT(0)
116121

117122
/* PMIIDR register field */
118-
#define ARM_CSPMU_PMIIDR_IMPLEMENTER GENMASK(11, 0)
119-
#define ARM_CSPMU_PMIIDR_PRODUCTID GENMASK(31, 20)
123+
#define PMIIDR_IMPLEMENTER GENMASK(11, 0)
124+
#define PMIIDR_IMPLEMENTER_DES_0 GENMASK(3, 0)
125+
#define PMIIDR_IMPLEMENTER_DES_1 GENMASK(6, 4)
126+
#define PMIIDR_IMPLEMENTER_DES_2 GENMASK(11, 8)
127+
#define PMIIDR_REVISION GENMASK(15, 12)
128+
#define PMIIDR_VARIANT GENMASK(19, 16)
129+
#define PMIIDR_PRODUCTID GENMASK(31, 20)
130+
#define PMIIDR_PRODUCTID_PART_0 GENMASK(27, 20)
131+
#define PMIIDR_PRODUCTID_PART_1 GENMASK(31, 28)
132+
133+
/* PMPIDR0 register field */
134+
#define PMPIDR0_PART_0 GENMASK(7, 0)
135+
136+
/* PMPIDR1 register field */
137+
#define PMPIDR1_DES_0 GENMASK(7, 4)
138+
#define PMPIDR1_PART_1 GENMASK(3, 0)
139+
140+
/* PMPIDR2 register field */
141+
#define PMPIDR2_REVISION GENMASK(7, 4)
142+
#define PMPIDR2_DES_1 GENMASK(2, 0)
143+
144+
/* PMPIDR3 register field */
145+
#define PMPIDR3_REVAND GENMASK(7, 4)
146+
#define PMPIDR3_CMOD GENMASK(3, 0)
147+
148+
/* PMPIDR4 register field */
149+
#define PMPIDR4_SIZE GENMASK(7, 4)
150+
#define PMPIDR4_DES_2 GENMASK(3, 0)
120151

121152
/* JEDEC-assigned JEP106 identification code */
122153
#define ARM_CSPMU_IMPL_ID_NVIDIA 0x36B

drivers/perf/arm_cspmu/nvidia_cspmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
322322
if (!ctx)
323323
return -ENOMEM;
324324

325-
prodid = FIELD_GET(ARM_CSPMU_PMIIDR_PRODUCTID, cspmu->impl.pmiidr);
325+
prodid = FIELD_GET(PMIIDR_PRODUCTID, cspmu->impl.pmiidr);
326326

327327
/* Find matching PMU. */
328328
for (; match->prodid; match++) {

0 commit comments

Comments
 (0)