4141
4242#define NUM_COUNTERS 11
4343#define CYCLES_COUNTER 0
44+ #define CYCLES_EVENT_ID 0
4445
4546#define CONFIG_EVENT_MASK GENMASK(7, 0)
46- #define CONFIG_COUNTER_MASK GENMASK(15, 8 )
47+ #define CONFIG_COUNTER_MASK GENMASK(23, 16 )
4748
4849#define to_ddr_pmu (p ) container_of(p, struct ddr_pmu, pmu)
4950
@@ -130,6 +131,9 @@ static ssize_t ddr_pmu_event_show(struct device *dev,
130131 return sysfs_emit (page , "event=0x%02llx\n" , pmu_attr -> id );
131132}
132133
134+ #define COUNTER_OFFSET_IN_EVENT 8
135+ #define ID (counter , id ) ((counter << COUNTER_OFFSET_IN_EVENT) | id)
136+
133137#define IMX9_DDR_PMU_EVENT_ATTR (_name , _id ) \
134138 (&((struct perf_pmu_events_attr[]) { \
135139 { .attr = __ATTR(_name, 0444, ddr_pmu_event_show, NULL),\
@@ -162,81 +166,81 @@ static struct attribute *ddr_perf_events_attrs[] = {
162166 IMX9_DDR_PMU_EVENT_ATTR (ddrc_pm_29 , 63 ),
163167
164168 /* 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 ) ),
173177
174178 /* 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 ) ),
185189
186190 /* 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 ) ),
197201
198202 /* 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 ) ),
209213
210214 /* 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 ) ),
220224
221225 /* 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 ) ),
224228
225229 /* 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 ) ),
228232
229233 /* 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 ) ),
232236
233237 /* 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 ) ),
236240
237241 /* 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 ) ),
240244 NULL ,
241245};
242246
@@ -245,7 +249,7 @@ static const struct attribute_group ddr_perf_events_attr_group = {
245249 .attrs = ddr_perf_events_attrs ,
246250};
247251
248- PMU_FORMAT_ATTR (event , "config:0-7" );
252+ PMU_FORMAT_ATTR (event , "config:0-7,16-23 " );
249253PMU_FORMAT_ATTR (counter , "config:8-15" );
250254PMU_FORMAT_ATTR (axi_id , "config1:0-17" );
251255PMU_FORMAT_ATTR (axi_mask , "config2:0-17" );
@@ -366,13 +370,10 @@ static void ddr_perf_counter_local_config(struct ddr_pmu *pmu, int config,
366370 }
367371}
368372
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 )
370375{
371376 u32 pmcfg1 , pmcfg2 ;
372- int event , counter ;
373-
374- event = FIELD_GET (CONFIG_EVENT_MASK , cfg );
375- counter = FIELD_GET (CONFIG_COUNTER_MASK , cfg );
376377
377378 pmcfg1 = readl_relaxed (pmu -> base + PMCFG1 );
378379
@@ -392,12 +393,12 @@ static void ddr_perf_monitor_config(struct ddr_pmu *pmu, int cfg, int cfg1, int
392393 pmcfg1 &= ~PMCFG1_RD_BT_FILT_EN ;
393394
394395 pmcfg1 &= ~FIELD_PREP (PMCFG1_ID_MASK , 0x3FFFF );
395- pmcfg1 |= FIELD_PREP (PMCFG1_ID_MASK , cfg2 );
396+ pmcfg1 |= FIELD_PREP (PMCFG1_ID_MASK , axi_mask );
396397 writel (pmcfg1 , pmu -> base + PMCFG1 );
397398
398399 pmcfg2 = readl_relaxed (pmu -> base + PMCFG2 );
399400 pmcfg2 &= ~FIELD_PREP (PMCFG2_ID , 0x3FFFF );
400- pmcfg2 |= FIELD_PREP (PMCFG2_ID , cfg1 );
401+ pmcfg2 |= FIELD_PREP (PMCFG2_ID , axi_id );
401402 writel (pmcfg2 , pmu -> base + PMCFG2 );
402403}
403404
@@ -465,17 +466,46 @@ static void ddr_perf_event_start(struct perf_event *event, int flags)
465466 hwc -> state = 0 ;
466467}
467468
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+
468491static int ddr_perf_event_add (struct perf_event * event , int flags )
469492{
470493 struct ddr_pmu * pmu = to_ddr_pmu (event -> pmu );
471494 struct hw_perf_event * hwc = & event -> hw ;
472495 int cfg = event -> attr .config ;
473496 int cfg1 = event -> attr .config1 ;
474497 int cfg2 = event -> attr .config2 ;
475- int counter ;
498+ int event_id , counter ;
476499
500+ event_id = FIELD_GET (CONFIG_EVENT_MASK , cfg );
477501 counter = FIELD_GET (CONFIG_COUNTER_MASK , cfg );
478502
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+
479509 pmu -> events [counter ] = event ;
480510 pmu -> active_events ++ ;
481511 hwc -> idx = counter ;
@@ -485,7 +515,7 @@ static int ddr_perf_event_add(struct perf_event *event, int flags)
485515 ddr_perf_event_start (event , flags );
486516
487517 /* 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 );
489519
490520 return 0 ;
491521}
@@ -506,9 +536,11 @@ static void ddr_perf_event_del(struct perf_event *event, int flags)
506536{
507537 struct ddr_pmu * pmu = to_ddr_pmu (event -> pmu );
508538 struct hw_perf_event * hwc = & event -> hw ;
539+ int counter = hwc -> idx ;
509540
510541 ddr_perf_event_stop (event , PERF_EF_UPDATE );
511542
543+ pmu -> events [counter ] = NULL ;
512544 pmu -> active_events -- ;
513545 hwc -> idx = -1 ;
514546}
0 commit comments