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.
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
---
drivers/perf/arm_cspmu/arm_cspmu.c | 44 +++++++++++++++++++++++++--
drivers/perf/arm_cspmu/arm_cspmu.h | 35 +++++++++++++++++++--
drivers/perf/arm_cspmu/nvidia_cspmu.c | 2 +-
3 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index 595e4bdd0b4b..347aefbd1704 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -323,14 +323,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,
},
@@ -352,6 +352,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)
@@ -362,7 +400,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),
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
index e3a4dd068805..7eb150abc3b7 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.h
+++ b/drivers/perf/arm_cspmu/arm_cspmu.h
@@ -87,6 +87,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)
@@ -116,8 +121,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
diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
index dc6d4e3e2a1b..b6cec351a142 100644
--- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
+++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
@@ -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++) {
--
2.47.0
On Tue, 12 Aug 2025, Besar Wicaksono wrote: > 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. > > Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com> Looks good to me Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com> > --- > drivers/perf/arm_cspmu/arm_cspmu.c | 44 +++++++++++++++++++++++++-- > drivers/perf/arm_cspmu/arm_cspmu.h | 35 +++++++++++++++++++-- > drivers/perf/arm_cspmu/nvidia_cspmu.c | 2 +- > 3 files changed, 75 insertions(+), 6 deletions(-) > > diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c > index 595e4bdd0b4b..347aefbd1704 100644 > --- a/drivers/perf/arm_cspmu/arm_cspmu.c > +++ b/drivers/perf/arm_cspmu/arm_cspmu.c > @@ -323,14 +323,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, > }, > @@ -352,6 +352,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) > @@ -362,7 +400,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), > diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h > index e3a4dd068805..7eb150abc3b7 100644 > --- a/drivers/perf/arm_cspmu/arm_cspmu.h > +++ b/drivers/perf/arm_cspmu/arm_cspmu.h > @@ -87,6 +87,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) > @@ -116,8 +121,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 > diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c > index dc6d4e3e2a1b..b6cec351a142 100644 > --- a/drivers/perf/arm_cspmu/nvidia_cspmu.c > +++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c > @@ -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++) { > -- > 2.47.0 > >
© 2016 - 2025 Red Hat, Inc.