Skip to content

Commit 1879a61

Browse files
committed
Merge branch 'for-next/perf-smmu' into for-next/perf
* for-next/perf-smmu: perf/smmuv3: Synthesize IIDR from CoreSight ID registers perf/smmuv3: Add devicetree support dt-bindings: Add Arm SMMUv3 PMCG binding
2 parents 8330904 + df457ca commit 1879a61

File tree

2 files changed

+134
-2
lines changed

2 files changed

+134
-2
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/perf/arm,smmu-v3-pmcg.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Arm SMMUv3 Performance Monitor Counter Group
8+
9+
maintainers:
10+
- Will Deacon <[email protected]>
11+
- Robin Murphy <[email protected]>
12+
13+
description: |
14+
An SMMUv3 may have several Performance Monitor Counter Group (PMCG).
15+
They are standalone performance monitoring units that support both
16+
architected and IMPLEMENTATION DEFINED event counters.
17+
18+
properties:
19+
$nodename:
20+
pattern: "^pmu@[0-9a-f]*"
21+
compatible:
22+
oneOf:
23+
- items:
24+
- const: arm,mmu-600-pmcg
25+
- const: arm,smmu-v3-pmcg
26+
- const: arm,smmu-v3-pmcg
27+
28+
reg:
29+
items:
30+
- description: Register page 0
31+
- description: Register page 1, if SMMU_PMCG_CFGR.RELOC_CTRS = 1
32+
minItems: 1
33+
34+
interrupts:
35+
maxItems: 1
36+
37+
msi-parent: true
38+
39+
required:
40+
- compatible
41+
- reg
42+
43+
anyOf:
44+
- required:
45+
- interrupts
46+
- required:
47+
- msi-parent
48+
49+
additionalProperties: false
50+
51+
examples:
52+
- |
53+
#include <dt-bindings/interrupt-controller/arm-gic.h>
54+
#include <dt-bindings/interrupt-controller/irq.h>
55+
56+
pmu@2b420000 {
57+
compatible = "arm,smmu-v3-pmcg";
58+
reg = <0x2b420000 0x1000>,
59+
<0x2b430000 0x1000>;
60+
interrupts = <GIC_SPI 80 IRQ_TYPE_EDGE_RISING>;
61+
msi-parent = <&its 0xff0000>;
62+
};
63+
64+
pmu@2b440000 {
65+
compatible = "arm,smmu-v3-pmcg";
66+
reg = <0x2b440000 0x1000>,
67+
<0x2b450000 0x1000>;
68+
interrupts = <GIC_SPI 81 IRQ_TYPE_EDGE_RISING>;
69+
msi-parent = <&its 0xff0000>;
70+
};

drivers/perf/arm_smmuv3_pmu.c

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <linux/kernel.h>
4848
#include <linux/list.h>
4949
#include <linux/msi.h>
50+
#include <linux/of.h>
5051
#include <linux/perf_event.h>
5152
#include <linux/platform_device.h>
5253
#include <linux/smp.h>
@@ -75,6 +76,10 @@
7576
#define SMMU_PMCG_CR 0xE04
7677
#define SMMU_PMCG_CR_ENABLE BIT(0)
7778
#define SMMU_PMCG_IIDR 0xE08
79+
#define SMMU_PMCG_IIDR_PRODUCTID GENMASK(31, 20)
80+
#define SMMU_PMCG_IIDR_VARIANT GENMASK(19, 16)
81+
#define SMMU_PMCG_IIDR_REVISION GENMASK(15, 12)
82+
#define SMMU_PMCG_IIDR_IMPLEMENTER GENMASK(11, 0)
7883
#define SMMU_PMCG_CEID0 0xE20
7984
#define SMMU_PMCG_CEID1 0xE28
8085
#define SMMU_PMCG_IRQ_CTRL 0xE50
@@ -83,6 +88,20 @@
8388
#define SMMU_PMCG_IRQ_CFG1 0xE60
8489
#define SMMU_PMCG_IRQ_CFG2 0xE64
8590

91+
/* IMP-DEF ID registers */
92+
#define SMMU_PMCG_PIDR0 0xFE0
93+
#define SMMU_PMCG_PIDR0_PART_0 GENMASK(7, 0)
94+
#define SMMU_PMCG_PIDR1 0xFE4
95+
#define SMMU_PMCG_PIDR1_DES_0 GENMASK(7, 4)
96+
#define SMMU_PMCG_PIDR1_PART_1 GENMASK(3, 0)
97+
#define SMMU_PMCG_PIDR2 0xFE8
98+
#define SMMU_PMCG_PIDR2_REVISION GENMASK(7, 4)
99+
#define SMMU_PMCG_PIDR2_DES_1 GENMASK(2, 0)
100+
#define SMMU_PMCG_PIDR3 0xFEC
101+
#define SMMU_PMCG_PIDR3_REVAND GENMASK(7, 4)
102+
#define SMMU_PMCG_PIDR4 0xFD0
103+
#define SMMU_PMCG_PIDR4_DES_2 GENMASK(3, 0)
104+
86105
/* MSI config fields */
87106
#define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2)
88107
#define MSI_CFG2_MEMATTR_DEVICE_nGnRE 0x1
@@ -754,6 +773,41 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu)
754773
dev_notice(smmu_pmu->dev, "option mask 0x%x\n", smmu_pmu->options);
755774
}
756775

776+
static bool smmu_pmu_coresight_id_regs(struct smmu_pmu *smmu_pmu)
777+
{
778+
return of_device_is_compatible(smmu_pmu->dev->of_node,
779+
"arm,mmu-600-pmcg");
780+
}
781+
782+
static void smmu_pmu_get_iidr(struct smmu_pmu *smmu_pmu)
783+
{
784+
u32 iidr = readl_relaxed(smmu_pmu->reg_base + SMMU_PMCG_IIDR);
785+
786+
if (!iidr && smmu_pmu_coresight_id_regs(smmu_pmu)) {
787+
u32 pidr0 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR0);
788+
u32 pidr1 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR1);
789+
u32 pidr2 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR2);
790+
u32 pidr3 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR3);
791+
u32 pidr4 = readl(smmu_pmu->reg_base + SMMU_PMCG_PIDR4);
792+
793+
u32 productid = FIELD_GET(SMMU_PMCG_PIDR0_PART_0, pidr0) |
794+
(FIELD_GET(SMMU_PMCG_PIDR1_PART_1, pidr1) << 8);
795+
u32 variant = FIELD_GET(SMMU_PMCG_PIDR2_REVISION, pidr2);
796+
u32 revision = FIELD_GET(SMMU_PMCG_PIDR3_REVAND, pidr3);
797+
u32 implementer =
798+
FIELD_GET(SMMU_PMCG_PIDR1_DES_0, pidr1) |
799+
(FIELD_GET(SMMU_PMCG_PIDR2_DES_1, pidr2) << 4) |
800+
(FIELD_GET(SMMU_PMCG_PIDR4_DES_2, pidr4) << 8);
801+
802+
iidr = FIELD_PREP(SMMU_PMCG_IIDR_PRODUCTID, productid) |
803+
FIELD_PREP(SMMU_PMCG_IIDR_VARIANT, variant) |
804+
FIELD_PREP(SMMU_PMCG_IIDR_REVISION, revision) |
805+
FIELD_PREP(SMMU_PMCG_IIDR_IMPLEMENTER, implementer);
806+
}
807+
808+
smmu_pmu->iidr = iidr;
809+
}
810+
757811
static int smmu_pmu_probe(struct platform_device *pdev)
758812
{
759813
struct smmu_pmu *smmu_pmu;
@@ -825,7 +879,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
825879
return err;
826880
}
827881

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

830884
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "smmuv3_pmcg_%llx",
831885
(res_0->start) >> SMMU_PMCG_PA_SHIFT);
@@ -834,7 +888,8 @@ static int smmu_pmu_probe(struct platform_device *pdev)
834888
return -EINVAL;
835889
}
836890

837-
smmu_pmu_get_acpi_options(smmu_pmu);
891+
if (!dev->of_node)
892+
smmu_pmu_get_acpi_options(smmu_pmu);
838893

839894
/* Pick one CPU to be the preferred one to use */
840895
smmu_pmu->on_cpu = raw_smp_processor_id();
@@ -884,9 +939,16 @@ static void smmu_pmu_shutdown(struct platform_device *pdev)
884939
smmu_pmu_disable(&smmu_pmu->pmu);
885940
}
886941

942+
static const struct of_device_id smmu_pmu_of_match[] = {
943+
{ .compatible = "arm,smmu-v3-pmcg" },
944+
{}
945+
};
946+
MODULE_DEVICE_TABLE(of, smmu_pmu_of_match);
947+
887948
static struct platform_driver smmu_pmu_driver = {
888949
.driver = {
889950
.name = "arm-smmu-v3-pmcg",
951+
.of_match_table = of_match_ptr(smmu_pmu_of_match),
890952
.suppress_bind_attrs = true,
891953
},
892954
.probe = smmu_pmu_probe,

0 commit comments

Comments
 (0)