41
41
42
42
#define NUM_COUNTERS 11
43
43
#define CYCLES_COUNTER 0
44
+ #define CYCLES_EVENT_ID 0
44
45
45
46
#define CONFIG_EVENT_MASK GENMASK(7, 0)
46
- #define CONFIG_COUNTER_MASK GENMASK(15, 8 )
47
+ #define CONFIG_COUNTER_MASK GENMASK(23, 16 )
47
48
48
49
#define to_ddr_pmu (p ) container_of(p, struct ddr_pmu, pmu)
49
50
@@ -130,6 +131,9 @@ static ssize_t ddr_pmu_event_show(struct device *dev,
130
131
return sysfs_emit (page , "event=0x%02llx\n" , pmu_attr -> id );
131
132
}
132
133
134
+ #define COUNTER_OFFSET_IN_EVENT 8
135
+ #define ID (counter , id ) ((counter << COUNTER_OFFSET_IN_EVENT) | id)
136
+
133
137
#define IMX9_DDR_PMU_EVENT_ATTR (_name , _id ) \
134
138
(&((struct perf_pmu_events_attr[]) { \
135
139
{ .attr = __ATTR(_name, 0444, ddr_pmu_event_show, NULL),\
@@ -162,81 +166,81 @@ static struct attribute *ddr_perf_events_attrs[] = {
162
166
IMX9_DDR_PMU_EVENT_ATTR (ddrc_pm_29 , 63 ),
163
167
164
168
/* counter1 specific events */
165
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_0 , 64 ),
166
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_1 , 65 ),
167
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_2 , 66 ),
168
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_3 , 67 ),
169
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_4 , 68 ),
170
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_5 , 69 ),
171
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_6 , 70 ),
172
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_7 , 71 ),
169
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_0 , ID ( 1 , 64 ) ),
170
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_1 , ID ( 1 , 65 ) ),
171
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_2 , ID ( 1 , 66 ) ),
172
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_3 , ID ( 1 , 67 ) ),
173
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_4 , ID ( 1 , 68 ) ),
174
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_5 , ID ( 1 , 69 ) ),
175
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_6 , ID ( 1 , 70 ) ),
176
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_riq_7 , ID ( 1 , 71 ) ),
173
177
174
178
/* counter2 specific events */
175
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_0 , 64 ),
176
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_1 , 65 ),
177
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_2 , 66 ),
178
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_3 , 67 ),
179
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_4 , 68 ),
180
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_5 , 69 ),
181
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_6 , 70 ),
182
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_7 , 71 ),
183
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_empty , 72 ),
184
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pm_rd_trans_filt , 73 ),
179
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_0 , ID ( 2 , 64 ) ),
180
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_1 , ID ( 2 , 65 ) ),
181
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_2 , ID ( 2 , 66 ) ),
182
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_3 , ID ( 2 , 67 ) ),
183
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_4 , ID ( 2 , 68 ) ),
184
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_5 , ID ( 2 , 69 ) ),
185
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_6 , ID ( 2 , 70 ) ),
186
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_ld_wiq_7 , ID ( 2 , 71 ) ),
187
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_empty , ID ( 2 , 72 ) ),
188
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pm_rd_trans_filt , ID ( 2 , 73 ) ),
185
189
186
190
/* counter3 specific events */
187
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_0 , 64 ),
188
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_1 , 65 ),
189
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_2 , 66 ),
190
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_3 , 67 ),
191
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_4 , 68 ),
192
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_5 , 69 ),
193
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_6 , 70 ),
194
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_7 , 71 ),
195
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_full , 72 ),
196
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pm_wr_trans_filt , 73 ),
191
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_0 , ID ( 3 , 64 ) ),
192
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_1 , ID ( 3 , 65 ) ),
193
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_2 , ID ( 3 , 66 ) ),
194
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_3 , ID ( 3 , 67 ) ),
195
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_4 , ID ( 3 , 68 ) ),
196
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_5 , ID ( 3 , 69 ) ),
197
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_6 , ID ( 3 , 70 ) ),
198
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_collision_7 , ID ( 3 , 71 ) ),
199
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_full , ID ( 3 , 72 ) ),
200
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pm_wr_trans_filt , ID ( 3 , 73 ) ),
197
201
198
202
/* counter4 specific events */
199
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_0 , 64 ),
200
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_1 , 65 ),
201
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_2 , 66 ),
202
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_3 , 67 ),
203
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_4 , 68 ),
204
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_5 , 69 ),
205
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_6 , 70 ),
206
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_7 , 71 ),
207
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_rdq2_rmw , 72 ),
208
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pm_rd_beat_filt , 73 ),
203
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_0 , ID ( 4 , 64 ) ),
204
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_1 , ID ( 4 , 65 ) ),
205
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_2 , ID ( 4 , 66 ) ),
206
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_3 , ID ( 4 , 67 ) ),
207
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_4 , ID ( 4 , 68 ) ),
208
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_5 , ID ( 4 , 69 ) ),
209
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_6 , ID ( 4 , 70 ) ),
210
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_row_open_7 , ID ( 4 , 71 ) ),
211
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_rdq2_rmw , ID ( 4 , 72 ) ),
212
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pm_rd_beat_filt , ID ( 4 , 73 ) ),
209
213
210
214
/* counter5 specific events */
211
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_0 , 64 ),
212
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_1 , 65 ),
213
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_2 , 66 ),
214
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_3 , 67 ),
215
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_4 , 68 ),
216
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_5 , 69 ),
217
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_6 , 70 ),
218
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_7 , 71 ),
219
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_rdq1 , 72 ),
215
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_0 , ID ( 5 , 64 ) ),
216
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_1 , ID ( 5 , 65 ) ),
217
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_2 , ID ( 5 , 66 ) ),
218
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_3 , ID ( 5 , 67 ) ),
219
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_4 , ID ( 5 , 68 ) ),
220
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_5 , ID ( 5 , 69 ) ),
221
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_6 , ID ( 5 , 70 ) ),
222
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_start_7 , ID ( 5 , 71 ) ),
223
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_rdq1 , ID ( 5 , 72 ) ),
220
224
221
225
/* counter6 specific events */
222
- IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_end_0 , 64 ),
223
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_rdq2 , 72 ),
226
+ IMX9_DDR_PMU_EVENT_ATTR (ddrc_qx_valid_end_0 , ID ( 6 , 64 ) ),
227
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_rdq2 , ID ( 6 , 72 ) ),
224
228
225
229
/* counter7 specific events */
226
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_1_2_full , 64 ),
227
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_wrq0 , 65 ),
230
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_1_2_full , ID ( 7 , 64 ) ),
231
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_wrq0 , ID ( 7 , 65 ) ),
228
232
229
233
/* counter8 specific events */
230
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_bias_switched , 64 ),
231
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_1_4_full , 65 ),
234
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_bias_switched , ID ( 8 , 64 ) ),
235
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_1_4_full , ID ( 8 , 65 ) ),
232
236
233
237
/* counter9 specific events */
234
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_wrq1 , 65 ),
235
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_3_4_full , 66 ),
238
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_wrq1 , ID ( 9 , 65 ) ),
239
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_3_4_full , ID ( 9 , 66 ) ),
236
240
237
241
/* counter10 specific events */
238
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_misc_mrk , 65 ),
239
- IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_rdq0 , 66 ),
242
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_misc_mrk , ID ( 10 , 65 ) ),
243
+ IMX9_DDR_PMU_EVENT_ATTR (eddrtq_pmon_ld_rdq0 , ID ( 10 , 66 ) ),
240
244
NULL ,
241
245
};
242
246
@@ -245,7 +249,7 @@ static const struct attribute_group ddr_perf_events_attr_group = {
245
249
.attrs = ddr_perf_events_attrs ,
246
250
};
247
251
248
- PMU_FORMAT_ATTR (event , "config:0-7" );
252
+ PMU_FORMAT_ATTR (event , "config:0-7,16-23 " );
249
253
PMU_FORMAT_ATTR (counter , "config:8-15" );
250
254
PMU_FORMAT_ATTR (axi_id , "config1:0-17" );
251
255
PMU_FORMAT_ATTR (axi_mask , "config2:0-17" );
@@ -366,13 +370,10 @@ static void ddr_perf_counter_local_config(struct ddr_pmu *pmu, int config,
366
370
}
367
371
}
368
372
369
- static void ddr_perf_monitor_config (struct ddr_pmu * pmu , int cfg , int cfg1 , int cfg2 )
373
+ static void ddr_perf_monitor_config (struct ddr_pmu * pmu , int event ,
374
+ int counter , int axi_id , int axi_mask )
370
375
{
371
376
u32 pmcfg1 , pmcfg2 ;
372
- int event , counter ;
373
-
374
- event = FIELD_GET (CONFIG_EVENT_MASK , cfg );
375
- counter = FIELD_GET (CONFIG_COUNTER_MASK , cfg );
376
377
377
378
pmcfg1 = readl_relaxed (pmu -> base + PMCFG1 );
378
379
@@ -392,12 +393,12 @@ static void ddr_perf_monitor_config(struct ddr_pmu *pmu, int cfg, int cfg1, int
392
393
pmcfg1 &= ~PMCFG1_RD_BT_FILT_EN ;
393
394
394
395
pmcfg1 &= ~FIELD_PREP (PMCFG1_ID_MASK , 0x3FFFF );
395
- pmcfg1 |= FIELD_PREP (PMCFG1_ID_MASK , cfg2 );
396
+ pmcfg1 |= FIELD_PREP (PMCFG1_ID_MASK , axi_mask );
396
397
writel (pmcfg1 , pmu -> base + PMCFG1 );
397
398
398
399
pmcfg2 = readl_relaxed (pmu -> base + PMCFG2 );
399
400
pmcfg2 &= ~FIELD_PREP (PMCFG2_ID , 0x3FFFF );
400
- pmcfg2 |= FIELD_PREP (PMCFG2_ID , cfg1 );
401
+ pmcfg2 |= FIELD_PREP (PMCFG2_ID , axi_id );
401
402
writel (pmcfg2 , pmu -> base + PMCFG2 );
402
403
}
403
404
@@ -465,17 +466,46 @@ static void ddr_perf_event_start(struct perf_event *event, int flags)
465
466
hwc -> state = 0 ;
466
467
}
467
468
469
+ static int ddr_perf_alloc_counter (struct ddr_pmu * pmu , int event , int counter )
470
+ {
471
+ int i ;
472
+
473
+ if (event == CYCLES_EVENT_ID ) {
474
+ // Cycles counter is dedicated for cycle event.
475
+ if (pmu -> events [CYCLES_COUNTER ] == NULL )
476
+ return CYCLES_COUNTER ;
477
+ } else if (counter != 0 ) {
478
+ // Counter specific event use specific counter.
479
+ if (pmu -> events [counter ] == NULL )
480
+ return counter ;
481
+ } else {
482
+ // Auto allocate counter for referene event.
483
+ for (i = 1 ; i < NUM_COUNTERS ; i ++ )
484
+ if (pmu -> events [i ] == NULL )
485
+ return i ;
486
+ }
487
+
488
+ return - ENOENT ;
489
+ }
490
+
468
491
static int ddr_perf_event_add (struct perf_event * event , int flags )
469
492
{
470
493
struct ddr_pmu * pmu = to_ddr_pmu (event -> pmu );
471
494
struct hw_perf_event * hwc = & event -> hw ;
472
495
int cfg = event -> attr .config ;
473
496
int cfg1 = event -> attr .config1 ;
474
497
int cfg2 = event -> attr .config2 ;
475
- int counter ;
498
+ int event_id , counter ;
476
499
500
+ event_id = FIELD_GET (CONFIG_EVENT_MASK , cfg );
477
501
counter = FIELD_GET (CONFIG_COUNTER_MASK , cfg );
478
502
503
+ counter = ddr_perf_alloc_counter (pmu , event_id , counter );
504
+ if (counter < 0 ) {
505
+ dev_dbg (pmu -> dev , "There are not enough counters\n" );
506
+ return - EOPNOTSUPP ;
507
+ }
508
+
479
509
pmu -> events [counter ] = event ;
480
510
pmu -> active_events ++ ;
481
511
hwc -> idx = counter ;
@@ -485,7 +515,7 @@ static int ddr_perf_event_add(struct perf_event *event, int flags)
485
515
ddr_perf_event_start (event , flags );
486
516
487
517
/* read trans, write trans, read beat */
488
- ddr_perf_monitor_config (pmu , cfg , cfg1 , cfg2 );
518
+ ddr_perf_monitor_config (pmu , event_id , counter , cfg1 , cfg2 );
489
519
490
520
return 0 ;
491
521
}
@@ -506,9 +536,11 @@ static void ddr_perf_event_del(struct perf_event *event, int flags)
506
536
{
507
537
struct ddr_pmu * pmu = to_ddr_pmu (event -> pmu );
508
538
struct hw_perf_event * hwc = & event -> hw ;
539
+ int counter = hwc -> idx ;
509
540
510
541
ddr_perf_event_stop (event , PERF_EF_UPDATE );
511
542
543
+ pmu -> events [counter ] = NULL ;
512
544
pmu -> active_events -- ;
513
545
hwc -> idx = -1 ;
514
546
}
0 commit comments