2121
2222#define NI_CHILD_NODE_INFO 0x004
2323#define NI_CHILD_PTR (n ) (0x008 + (n) * 4)
24+ #define NI_NUM_SUB_FEATURES 0x100
25+ #define NI_SUB_FEATURE_TYPE (n ) (0x108 + (n) * 8)
26+ #define NI_SUB_FEATURE_PTR (n ) (0x10c + (n) * 8)
27+
28+ #define NI_SUB_FEATURE_TYPE_FCU 0x2
2429
2530#define NI700_PMUSELA 0x00c
2631
3338#define NI_PIDR2_VERSION GENMASK(7, 4)
3439
3540/* PMU node */
36- #define NI_PMEVCNTR (n ) (0x008 + (n) * 8)
37- #define NI_PMCCNTR_L 0x0f8
38- #define NI_PMCCNTR_U 0x0fc
41+ #define NI700_PMEVCNTR (n ) (0x008 + (n) * 8)
42+ #define NI700_PMCCNTR_L 0x0f8
43+ #define NI_PMEVCNTR (n ) (0x200 + (n) * 8)
44+ #define NI_PMCCNTR_L 0x2f8
3945#define NI_PMEVTYPER (n ) (0x400 + (n) * 4)
4046#define NI_PMEVTYPER_NODE_TYPE GENMASK(12, 9)
4147#define NI_PMEVTYPER_NODE_ID GENMASK(8, 0)
6672enum ni_part {
6773 PART_NI_700 = 0x43b ,
6874 PART_NI_710AE = 0x43d ,
75+ PART_NOC_S3 = 0x43f ,
76+ PART_SI_L1 = 0x455 ,
6977};
7078
7179enum ni_node_type {
@@ -79,6 +87,10 @@ enum ni_node_type {
7987 NI_HSNI ,
8088 NI_HMNI ,
8189 NI_PMNI ,
90+ NI_TSNI ,
91+ NI_TMNI ,
92+ NI_CMNI = 0x0e ,
93+ NI_MCN = 0x63 ,
8294};
8395
8496struct arm_ni_node {
@@ -179,6 +191,9 @@ static struct attribute *arm_ni_event_attrs[] = {
179191 NI_EVENT_ATTR (hsni , NI_HSNI ),
180192 NI_EVENT_ATTR (hmni , NI_HMNI ),
181193 NI_EVENT_ATTR (pmni , NI_PMNI ),
194+ NI_EVENT_ATTR (tsni , NI_TSNI ),
195+ NI_EVENT_ATTR (tmni , NI_TMNI ),
196+ NI_EVENT_ATTR (cmni , NI_CMNI ),
182197 NULL
183198};
184199
@@ -332,16 +347,16 @@ static int arm_ni_event_init(struct perf_event *event)
332347 return - EINVAL ;
333348}
334349
335- static u64 arm_ni_read_ccnt (struct arm_ni_cd * cd )
350+ static u64 arm_ni_read_ccnt (void __iomem * pmccntr )
336351{
337352 u64 l , u_old , u_new ;
338353 int retries = 3 ; /* 1st time unlucky, 2nd improbable, 3rd just broken */
339354
340- u_new = readl_relaxed (cd -> pmu_base + NI_PMCCNTR_U );
355+ u_new = readl_relaxed (pmccntr + 4 );
341356 do {
342357 u_old = u_new ;
343- l = readl_relaxed (cd -> pmu_base + NI_PMCCNTR_L );
344- u_new = readl_relaxed (cd -> pmu_base + NI_PMCCNTR_U );
358+ l = readl_relaxed (pmccntr );
359+ u_new = readl_relaxed (pmccntr + 4 );
345360 } while (u_new != u_old && -- retries );
346361 WARN_ON (!retries );
347362
@@ -350,17 +365,16 @@ static u64 arm_ni_read_ccnt(struct arm_ni_cd *cd)
350365
351366static void arm_ni_event_read (struct perf_event * event )
352367{
353- struct arm_ni_cd * cd = pmu_to_cd (event -> pmu );
354368 struct hw_perf_event * hw = & event -> hw ;
355369 u64 count , prev ;
356370 bool ccnt = hw -> idx == NI_CCNT_IDX ;
357371
358372 do {
359373 prev = local64_read (& hw -> prev_count );
360374 if (ccnt )
361- count = arm_ni_read_ccnt (cd );
375+ count = arm_ni_read_ccnt (( void __iomem * ) event -> hw . event_base );
362376 else
363- count = readl_relaxed (cd -> pmu_base + NI_PMEVCNTR ( hw -> idx ) );
377+ count = readl_relaxed (( void __iomem * ) event -> hw . event_base );
364378 } while (local64_cmpxchg (& hw -> prev_count , prev , count ) != prev );
365379
366380 count -= prev ;
@@ -385,16 +399,21 @@ static void arm_ni_event_stop(struct perf_event *event, int flags)
385399 arm_ni_event_read (event );
386400}
387401
388- static void arm_ni_init_ccnt (struct arm_ni_cd * cd )
402+ static void arm_ni_init_ccnt (struct hw_perf_event * hw )
403+ {
404+ local64_set (& hw -> prev_count , S64_MIN );
405+ lo_hi_writeq_relaxed (S64_MIN , (void __iomem * )hw -> event_base );
406+ }
407+
408+ static void arm_ni_init_evcnt (struct hw_perf_event * hw )
389409{
390- local64_set (& cd -> ccnt -> hw . prev_count , S64_MIN );
391- lo_hi_writeq_relaxed ( S64_MIN , cd -> pmu_base + NI_PMCCNTR_L );
410+ local64_set (& hw -> prev_count , S32_MIN );
411+ writel_relaxed ( S32_MIN , ( void __iomem * ) hw -> event_base );
392412}
393413
394- static void arm_ni_init_evcnt ( struct arm_ni_cd * cd , int idx )
414+ static bool arm_ni_is_7xx ( const struct arm_ni * ni )
395415{
396- local64_set (& cd -> evcnt [idx ]-> hw .prev_count , S32_MIN );
397- writel_relaxed (S32_MIN , cd -> pmu_base + NI_PMEVCNTR (idx ));
416+ return ni -> part == PART_NI_700 || ni -> part == PART_NI_710AE ;
398417}
399418
400419static int arm_ni_event_add (struct perf_event * event , int flags )
@@ -403,14 +422,17 @@ static int arm_ni_event_add(struct perf_event *event, int flags)
403422 struct hw_perf_event * hw = & event -> hw ;
404423 struct arm_ni_unit * unit ;
405424 enum ni_node_type type = NI_EVENT_TYPE (event );
425+ bool is_7xx = arm_ni_is_7xx (cd_to_ni (cd ));
406426 u32 reg ;
407427
408428 if (type == NI_PMU ) {
409429 if (cd -> ccnt )
410430 return - ENOSPC ;
411431 hw -> idx = NI_CCNT_IDX ;
432+ hw -> event_base = (unsigned long )cd -> pmu_base +
433+ is_7xx ? NI700_PMCCNTR_L : NI_PMCCNTR_L ;
412434 cd -> ccnt = event ;
413- arm_ni_init_ccnt (cd );
435+ arm_ni_init_ccnt (hw );
414436 } else {
415437 hw -> idx = 0 ;
416438 while (cd -> evcnt [hw -> idx ]) {
@@ -420,7 +442,9 @@ static int arm_ni_event_add(struct perf_event *event, int flags)
420442 cd -> evcnt [hw -> idx ] = event ;
421443 unit = (void * )hw -> config_base ;
422444 unit -> event [hw -> idx ] = NI_EVENT_EVENTID (event );
423- arm_ni_init_evcnt (cd , hw -> idx );
445+ hw -> event_base = (unsigned long )cd -> pmu_base +
446+ is_7xx ? NI700_PMEVCNTR (hw -> idx ) : NI_PMEVCNTR (hw -> idx );
447+ arm_ni_init_evcnt (hw );
424448 lo_hi_writeq_relaxed (le64_to_cpu (unit -> pmusel ), unit -> pmusela );
425449
426450 reg = FIELD_PREP (NI_PMEVTYPER_NODE_TYPE , type ) |
@@ -457,7 +481,7 @@ static irqreturn_t arm_ni_handle_irq(int irq, void *dev_id)
457481 ret = IRQ_HANDLED ;
458482 if (!(WARN_ON (!cd -> ccnt ))) {
459483 arm_ni_event_read (cd -> ccnt );
460- arm_ni_init_ccnt (cd );
484+ arm_ni_init_ccnt (& cd -> ccnt -> hw );
461485 }
462486 }
463487 for (int i = 0 ; i < NI_NUM_COUNTERS ; i ++ ) {
@@ -466,7 +490,7 @@ static irqreturn_t arm_ni_handle_irq(int irq, void *dev_id)
466490 ret = IRQ_HANDLED ;
467491 if (!(WARN_ON (!cd -> evcnt [i ]))) {
468492 arm_ni_event_read (cd -> evcnt [i ]);
469- arm_ni_init_evcnt (cd , i );
493+ arm_ni_init_evcnt (& cd -> evcnt [ i ] -> hw );
470494 }
471495 }
472496 writel_relaxed (reg , cd -> pmu_base + NI_PMOVSCLR );
@@ -476,6 +500,25 @@ static irqreturn_t arm_ni_handle_irq(int irq, void *dev_id)
476500 }
477501}
478502
503+ static void __iomem * arm_ni_get_pmusel (struct arm_ni * ni , void __iomem * unit_base )
504+ {
505+ u32 type , ptr , num ;
506+
507+ if (arm_ni_is_7xx (ni ))
508+ return unit_base + NI700_PMUSELA ;
509+
510+ num = readl_relaxed (unit_base + NI_NUM_SUB_FEATURES );
511+ for (int i = 0 ; i < num ; i ++ ) {
512+ type = readl_relaxed (unit_base + NI_SUB_FEATURE_TYPE (i ));
513+ if (type != NI_SUB_FEATURE_TYPE_FCU )
514+ continue ;
515+ ptr = readl_relaxed (unit_base + NI_SUB_FEATURE_PTR (i ));
516+ return ni -> base + ptr ;
517+ }
518+ /* Should be impossible */
519+ return NULL ;
520+ }
521+
479522static int arm_ni_init_cd (struct arm_ni * ni , struct arm_ni_node * node , u64 res_start )
480523{
481524 struct arm_ni_cd * cd = ni -> cds + node -> id ;
@@ -512,13 +555,18 @@ static int arm_ni_init_cd(struct arm_ni *ni, struct arm_ni_node *node, u64 res_s
512555 case NI_HSNI :
513556 case NI_HMNI :
514557 case NI_PMNI :
515- unit -> pmusela = unit_base + NI700_PMUSELA ;
558+ case NI_TSNI :
559+ case NI_TMNI :
560+ case NI_CMNI :
561+ unit -> pmusela = arm_ni_get_pmusel (ni , unit_base );
516562 writel_relaxed (1 , unit -> pmusela );
517563 if (readl_relaxed (unit -> pmusela ) != 1 )
518564 dev_info (ni -> dev , "No access to node 0x%04x%04x\n" , unit -> id , unit -> type );
519565 else
520566 unit -> ns = true;
521567 break ;
568+ case NI_MCN :
569+ break ;
522570 default :
523571 /*
524572 * e.g. FMU - thankfully bits 3:2 of FMU_ERR_FR0 are RES0 so
@@ -649,6 +697,8 @@ static int arm_ni_probe(struct platform_device *pdev)
649697 switch (part ) {
650698 case PART_NI_700 :
651699 case PART_NI_710AE :
700+ case PART_NOC_S3 :
701+ case PART_SI_L1 :
652702 break ;
653703 default :
654704 dev_WARN (& pdev -> dev , "Unknown part number: 0x%03x, this may go badly\n" , part );
0 commit comments