Skip to content

Commit d0d7c66

Browse files
Xu Yangwilldeacon
authored andcommitted
perf: imx_perf: add support for i.MX95 platform
i.MX95 has a DDR PMU which is almostly same as i.MX93, it now supports read beat and write beat filter capabilities. This will add support for i.MX95 and enhance the driver to support specific filter handling for it. Usage: For read beat: ~# perf stat -a -I 1000 -e imx9_ddr0/eddrtq_pm_rd_beat_filt2,axi_mask=ID_MASK,axi_id=ID/ ~# perf stat -a -I 1000 -e imx9_ddr0/eddrtq_pm_rd_beat_filt1,axi_mask=ID_MASK,axi_id=ID/ ~# perf stat -a -I 1000 -e imx9_ddr0/eddrtq_pm_rd_beat_filt0,axi_mask=ID_MASK,axi_id=ID/ eg: For edma2: perf stat -a -I 1000 -e imx9_ddr0/eddrtq_pm_rd_beat_filt0,axi_mask=0x00f,axi_id=0x00c/ For write beat: ~# perf stat -a -I 1000 -e imx9_ddr0/eddrtq_pm_wr_beat_filt,axi_mask=ID_MASK,axi_id=ID/ eg: For edma2: perf stat -a -I 1000 -e imx9_ddr0/eddrtq_pm_wr_beat_filt,axi_mask=0x00f,axi_id=0x00c/ Reviewed-by: Frank Li <[email protected]> Signed-off-by: Xu Yang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent ac9aa29 commit d0d7c66

File tree

1 file changed

+86
-3
lines changed

1 file changed

+86
-3
lines changed

drivers/perf/fsl_imx9_ddr_perf.c

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,19 @@
1717
#define MX93_PMCFG1_RD_BT_FILT_EN BIT(29)
1818
#define MX93_PMCFG1_ID_MASK GENMASK(17, 0)
1919

20+
#define MX95_PMCFG1_WR_BEAT_FILT_EN BIT(31)
21+
#define MX95_PMCFG1_RD_BEAT_FILT_EN BIT(30)
22+
2023
#define PMCFG2 0x04
2124
#define MX93_PMCFG2_ID GENMASK(17, 0)
2225

26+
#define PMCFG3 0x08
27+
#define PMCFG4 0x0C
28+
#define PMCFG5 0x10
29+
#define PMCFG6 0x14
30+
#define MX95_PMCFG_ID_MASK GENMASK(9, 0)
31+
#define MX95_PMCFG_ID GENMASK(25, 16)
32+
2333
/* Global control register affects all counters and takes priority over local control registers */
2434
#define PMGC0 0x40
2535
/* Global control register bits */
@@ -75,13 +85,23 @@ static const struct imx_ddr_devtype_data imx93_devtype_data = {
7585
.identifier = "imx93",
7686
};
7787

88+
static const struct imx_ddr_devtype_data imx95_devtype_data = {
89+
.identifier = "imx95",
90+
};
91+
7892
static inline bool is_imx93(struct ddr_pmu *pmu)
7993
{
8094
return pmu->devtype_data == &imx93_devtype_data;
8195
}
8296

97+
static inline bool is_imx95(struct ddr_pmu *pmu)
98+
{
99+
return pmu->devtype_data == &imx95_devtype_data;
100+
}
101+
83102
static const struct of_device_id imx_ddr_pmu_dt_ids[] = {
84-
{.compatible = "fsl,imx93-ddr-pmu", .data = &imx93_devtype_data},
103+
{ .compatible = "fsl,imx93-ddr-pmu", .data = &imx93_devtype_data },
104+
{ .compatible = "fsl,imx95-ddr-pmu", .data = &imx95_devtype_data },
85105
{ /* sentinel */ }
86106
};
87107
MODULE_DEVICE_TABLE(of, imx_ddr_pmu_dt_ids);
@@ -158,6 +178,9 @@ static ssize_t ddr_pmu_event_show(struct device *dev,
158178
#define IMX93_DDR_PMU_EVENT_ATTR(_name, _id) \
159179
DDR_PMU_EVENT_ATTR_COMM(_name, _id, &imx93_devtype_data)
160180

181+
#define IMX95_DDR_PMU_EVENT_ATTR(_name, _id) \
182+
DDR_PMU_EVENT_ATTR_COMM(_name, _id, &imx95_devtype_data)
183+
161184
static struct attribute *ddr_perf_events_attrs[] = {
162185
/* counter0 cycles event */
163186
IMX9_DDR_PMU_EVENT_ATTR(cycles, 0),
@@ -204,6 +227,7 @@ static struct attribute *ddr_perf_events_attrs[] = {
204227
IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_7, ID(2, 71)),
205228
IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_empty, ID(2, 72)),
206229
IMX93_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_trans_filt, ID(2, 73)), /* imx93 specific*/
230+
IMX95_DDR_PMU_EVENT_ATTR(eddrtq_pm_wr_beat_filt, ID(2, 73)), /* imx95 specific*/
207231

208232
/* counter3 specific events */
209233
IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_0, ID(3, 64)),
@@ -216,6 +240,7 @@ static struct attribute *ddr_perf_events_attrs[] = {
216240
IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_7, ID(3, 71)),
217241
IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_full, ID(3, 72)),
218242
IMX93_DDR_PMU_EVENT_ATTR(eddrtq_pm_wr_trans_filt, ID(3, 73)), /* imx93 specific*/
243+
IMX95_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt2, ID(3, 73)), /* imx95 specific*/
219244

220245
/* counter4 specific events */
221246
IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_0, ID(4, 64)),
@@ -228,6 +253,7 @@ static struct attribute *ddr_perf_events_attrs[] = {
228253
IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_7, ID(4, 71)),
229254
IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2_rmw, ID(4, 72)),
230255
IMX93_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt, ID(4, 73)), /* imx93 specific*/
256+
IMX95_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt1, ID(4, 73)), /* imx95 specific*/
231257

232258
/* counter5 specific events */
233259
IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_0, ID(5, 64)),
@@ -239,6 +265,7 @@ static struct attribute *ddr_perf_events_attrs[] = {
239265
IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_6, ID(5, 70)),
240266
IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_7, ID(5, 71)),
241267
IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq1, ID(5, 72)),
268+
IMX95_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt0, ID(5, 73)), /* imx95 specific*/
242269

243270
/* counter6 specific events */
244271
IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_end_0, ID(6, 64)),
@@ -432,6 +459,57 @@ static void imx93_ddr_perf_monitor_config(struct ddr_pmu *pmu, int event,
432459
writel_relaxed(pmcfg2, pmu->base + PMCFG2);
433460
}
434461

462+
static void imx95_ddr_perf_monitor_config(struct ddr_pmu *pmu, int event,
463+
int counter, int axi_id, int axi_mask)
464+
{
465+
u32 pmcfg1, pmcfg, offset = 0;
466+
467+
pmcfg1 = readl_relaxed(pmu->base + PMCFG1);
468+
469+
if (event == 73) {
470+
switch (counter) {
471+
case 2:
472+
pmcfg1 |= MX95_PMCFG1_WR_BEAT_FILT_EN;
473+
offset = PMCFG3;
474+
break;
475+
case 3:
476+
pmcfg1 |= MX95_PMCFG1_RD_BEAT_FILT_EN;
477+
offset = PMCFG4;
478+
break;
479+
case 4:
480+
pmcfg1 |= MX95_PMCFG1_RD_BEAT_FILT_EN;
481+
offset = PMCFG5;
482+
break;
483+
case 5:
484+
pmcfg1 |= MX95_PMCFG1_RD_BEAT_FILT_EN;
485+
offset = PMCFG6;
486+
break;
487+
}
488+
} else {
489+
switch (counter) {
490+
case 2:
491+
pmcfg1 &= ~MX95_PMCFG1_WR_BEAT_FILT_EN;
492+
break;
493+
case 3:
494+
case 4:
495+
case 5:
496+
pmcfg1 &= ~MX95_PMCFG1_RD_BEAT_FILT_EN;
497+
break;
498+
}
499+
}
500+
501+
writel_relaxed(pmcfg1, pmu->base + PMCFG1);
502+
503+
if (offset) {
504+
pmcfg = readl_relaxed(pmu->base + offset);
505+
pmcfg &= ~(FIELD_PREP(MX95_PMCFG_ID_MASK, 0x3FF) |
506+
FIELD_PREP(MX95_PMCFG_ID, 0x3FF));
507+
pmcfg |= (FIELD_PREP(MX95_PMCFG_ID_MASK, axi_mask) |
508+
FIELD_PREP(MX95_PMCFG_ID, axi_id));
509+
writel_relaxed(pmcfg, pmu->base + offset);
510+
}
511+
}
512+
435513
static void ddr_perf_event_update(struct perf_event *event)
436514
{
437515
struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
@@ -541,8 +619,13 @@ static int ddr_perf_event_add(struct perf_event *event, int flags)
541619
hwc->idx = counter;
542620
hwc->state |= PERF_HES_STOPPED;
543621

544-
/* read trans, write trans, read beat */
545-
imx93_ddr_perf_monitor_config(pmu, event_id, counter, cfg1, cfg2);
622+
if (is_imx93(pmu))
623+
/* read trans, write trans, read beat */
624+
imx93_ddr_perf_monitor_config(pmu, event_id, counter, cfg1, cfg2);
625+
626+
if (is_imx95(pmu))
627+
/* write beat, read beat2, read beat1, read beat */
628+
imx95_ddr_perf_monitor_config(pmu, event_id, counter, cfg1, cfg2);
546629

547630
if (flags & PERF_EF_START)
548631
ddr_perf_event_start(event, flags);

0 commit comments

Comments
 (0)