44
44
#define CMN_MAX_DTMS (CMN_MAX_XPS + (CMN_MAX_DIMENSION - 1) * 4)
45
45
46
46
/* The CFG node has various info besides the discovery tree */
47
- #define CMN_CFGM_PERIPH_ID_2 0x0010
48
- #define CMN_CFGM_PID2_REVISION GENMASK(7, 4)
47
+ #define CMN_CFGM_PERIPH_ID_01 0x0008
48
+ #define CMN_CFGM_PID0_PART_0 GENMASK_ULL(7, 0)
49
+ #define CMN_CFGM_PID1_PART_1 GENMASK_ULL(35, 32)
50
+ #define CMN_CFGM_PERIPH_ID_23 0x0010
51
+ #define CMN_CFGM_PID2_REVISION GENMASK_ULL(7, 4)
49
52
50
53
#define CMN_CFGM_INFO_GLOBAL 0x900
51
54
#define CMN_INFO_MULTIPLE_DTM_EN BIT_ULL(63)
186
189
#define CMN_WP_DOWN 2
187
190
188
191
192
+ /* Internal values for encoding event support */
189
193
enum cmn_model {
190
194
CMN600 = 1 ,
191
195
CMN650 = 2 ,
@@ -197,26 +201,34 @@ enum cmn_model {
197
201
CMN_650ON = CMN650 | CMN700 ,
198
202
};
199
203
204
+ /* Actual part numbers and revision IDs defined by the hardware */
205
+ enum cmn_part {
206
+ PART_CMN600 = 0x434 ,
207
+ PART_CMN650 = 0x436 ,
208
+ PART_CMN700 = 0x43c ,
209
+ PART_CI700 = 0x43a ,
210
+ };
211
+
200
212
/* CMN-600 r0px shouldn't exist in silicon, thankfully */
201
213
enum cmn_revision {
202
- CMN600_R1P0 ,
203
- CMN600_R1P1 ,
204
- CMN600_R1P2 ,
205
- CMN600_R1P3 ,
206
- CMN600_R2P0 ,
207
- CMN600_R3P0 ,
208
- CMN600_R3P1 ,
209
- CMN650_R0P0 = 0 ,
210
- CMN650_R1P0 ,
211
- CMN650_R1P1 ,
212
- CMN650_R2P0 ,
213
- CMN650_R1P2 ,
214
- CMN700_R0P0 = 0 ,
215
- CMN700_R1P0 ,
216
- CMN700_R2P0 ,
217
- CI700_R0P0 = 0 ,
218
- CI700_R1P0 ,
219
- CI700_R2P0 ,
214
+ REV_CMN600_R1P0 ,
215
+ REV_CMN600_R1P1 ,
216
+ REV_CMN600_R1P2 ,
217
+ REV_CMN600_R1P3 ,
218
+ REV_CMN600_R2P0 ,
219
+ REV_CMN600_R3P0 ,
220
+ REV_CMN600_R3P1 ,
221
+ REV_CMN650_R0P0 = 0 ,
222
+ REV_CMN650_R1P0 ,
223
+ REV_CMN650_R1P1 ,
224
+ REV_CMN650_R2P0 ,
225
+ REV_CMN650_R1P2 ,
226
+ REV_CMN700_R0P0 = 0 ,
227
+ REV_CMN700_R1P0 ,
228
+ REV_CMN700_R2P0 ,
229
+ REV_CI700_R0P0 = 0 ,
230
+ REV_CI700_R1P0 ,
231
+ REV_CI700_R2P0 ,
220
232
};
221
233
222
234
enum cmn_node_type {
@@ -306,7 +318,7 @@ struct arm_cmn {
306
318
unsigned int state ;
307
319
308
320
enum cmn_revision rev ;
309
- enum cmn_model model ;
321
+ enum cmn_part part ;
310
322
u8 mesh_x ;
311
323
u8 mesh_y ;
312
324
u16 num_xps ;
@@ -394,19 +406,35 @@ static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
394
406
return NULL ;
395
407
}
396
408
409
+ static enum cmn_model arm_cmn_model (const struct arm_cmn * cmn )
410
+ {
411
+ switch (cmn -> part ) {
412
+ case PART_CMN600 :
413
+ return CMN600 ;
414
+ case PART_CMN650 :
415
+ return CMN650 ;
416
+ case PART_CMN700 :
417
+ return CMN700 ;
418
+ case PART_CI700 :
419
+ return CI700 ;
420
+ default :
421
+ return 0 ;
422
+ };
423
+ }
424
+
397
425
static u32 arm_cmn_device_connect_info (const struct arm_cmn * cmn ,
398
426
const struct arm_cmn_node * xp , int port )
399
427
{
400
428
int offset = CMN_MXP__CONNECT_INFO (port );
401
429
402
430
if (port >= 2 ) {
403
- if (cmn -> model & ( CMN600 | CMN650 ) )
431
+ if (cmn -> part == PART_CMN600 || cmn -> part == PART_CMN650 )
404
432
return 0 ;
405
433
/*
406
434
* CI-700 may have extra ports, but still has the
407
435
* mesh_port_connect_info registers in the way.
408
436
*/
409
- if (cmn -> model == CI700 )
437
+ if (cmn -> part == PART_CI700 )
410
438
offset += CI700_CONNECT_INFO_P2_5_OFFSET ;
411
439
}
412
440
@@ -640,7 +668,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
640
668
641
669
eattr = container_of (attr , typeof (* eattr ), attr .attr );
642
670
643
- if (!(eattr -> model & cmn -> model ))
671
+ if (!(eattr -> model & arm_cmn_model ( cmn ) ))
644
672
return 0 ;
645
673
646
674
type = eattr -> type ;
@@ -658,7 +686,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
658
686
if ((intf & 4 ) && !(cmn -> ports_used & BIT (intf & 3 )))
659
687
return 0 ;
660
688
661
- if (chan == 4 && cmn -> model == CMN600 )
689
+ if (chan == 4 && cmn -> part == PART_CMN600 )
662
690
return 0 ;
663
691
664
692
if ((chan == 5 && cmn -> rsp_vc_num < 2 ) ||
@@ -669,36 +697,36 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
669
697
}
670
698
671
699
/* Revision-specific differences */
672
- if (cmn -> model == CMN600 ) {
673
- if (cmn -> rev < CMN600_R1P3 ) {
700
+ if (cmn -> part == PART_CMN600 ) {
701
+ if (cmn -> rev < REV_CMN600_R1P3 ) {
674
702
if (type == CMN_TYPE_CXRA && eventid > 0x10 )
675
703
return 0 ;
676
704
}
677
- if (cmn -> rev < CMN600_R1P2 ) {
705
+ if (cmn -> rev < REV_CMN600_R1P2 ) {
678
706
if (type == CMN_TYPE_HNF && eventid == 0x1b )
679
707
return 0 ;
680
708
if (type == CMN_TYPE_CXRA || type == CMN_TYPE_CXHA )
681
709
return 0 ;
682
710
}
683
- } else if (cmn -> model == CMN650 ) {
684
- if (cmn -> rev < CMN650_R2P0 || cmn -> rev == CMN650_R1P2 ) {
711
+ } else if (cmn -> part == PART_CMN650 ) {
712
+ if (cmn -> rev < REV_CMN650_R2P0 || cmn -> rev == REV_CMN650_R1P2 ) {
685
713
if (type == CMN_TYPE_HNF && eventid > 0x22 )
686
714
return 0 ;
687
715
if (type == CMN_TYPE_SBSX && eventid == 0x17 )
688
716
return 0 ;
689
717
if (type == CMN_TYPE_RNI && eventid > 0x10 )
690
718
return 0 ;
691
719
}
692
- } else if (cmn -> model == CMN700 ) {
693
- if (cmn -> rev < CMN700_R2P0 ) {
720
+ } else if (cmn -> part == PART_CMN700 ) {
721
+ if (cmn -> rev < REV_CMN700_R2P0 ) {
694
722
if (type == CMN_TYPE_HNF && eventid > 0x2c )
695
723
return 0 ;
696
724
if (type == CMN_TYPE_CCHA && eventid > 0x74 )
697
725
return 0 ;
698
726
if (type == CMN_TYPE_CCLA && eventid > 0x27 )
699
727
return 0 ;
700
728
}
701
- if (cmn -> rev < CMN700_R1P0 ) {
729
+ if (cmn -> rev < REV_CMN700_R1P0 ) {
702
730
if (type == CMN_TYPE_HNF && eventid > 0x2b )
703
731
return 0 ;
704
732
}
@@ -1200,7 +1228,7 @@ static u32 arm_cmn_wp_config(struct perf_event *event)
1200
1228
u32 grp = CMN_EVENT_WP_GRP (event );
1201
1229
u32 exc = CMN_EVENT_WP_EXCLUSIVE (event );
1202
1230
u32 combine = CMN_EVENT_WP_COMBINE (event );
1203
- bool is_cmn600 = to_cmn (event -> pmu )-> model == CMN600 ;
1231
+ bool is_cmn600 = to_cmn (event -> pmu )-> part == PART_CMN600 ;
1204
1232
1205
1233
config = FIELD_PREP (CMN_DTM_WPn_CONFIG_WP_DEV_SEL , dev ) |
1206
1234
FIELD_PREP (CMN_DTM_WPn_CONFIG_WP_CHN_SEL , chn ) |
@@ -1520,14 +1548,14 @@ static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
1520
1548
return ret ;
1521
1549
}
1522
1550
1523
- static enum cmn_filter_select arm_cmn_filter_sel (enum cmn_model model ,
1551
+ static enum cmn_filter_select arm_cmn_filter_sel (const struct arm_cmn * cmn ,
1524
1552
enum cmn_node_type type ,
1525
1553
unsigned int eventid )
1526
1554
{
1527
1555
struct arm_cmn_event_attr * e ;
1528
- int i ;
1556
+ enum cmn_model model = arm_cmn_model ( cmn ) ;
1529
1557
1530
- for (i = 0 ; i < ARRAY_SIZE (arm_cmn_event_attrs ) - 1 ; i ++ ) {
1558
+ for (int i = 0 ; i < ARRAY_SIZE (arm_cmn_event_attrs ) - 1 ; i ++ ) {
1531
1559
e = container_of (arm_cmn_event_attrs [i ], typeof (* e ), attr .attr );
1532
1560
if (e -> model & model && e -> type == type && e -> eventid == eventid )
1533
1561
return e -> fsel ;
@@ -1570,12 +1598,12 @@ static int arm_cmn_event_init(struct perf_event *event)
1570
1598
/* ...but the DTM may depend on which port we're watching */
1571
1599
if (cmn -> multi_dtm )
1572
1600
hw -> dtm_offset = CMN_EVENT_WP_DEV_SEL (event ) / 2 ;
1573
- } else if (type == CMN_TYPE_XP && cmn -> model == CMN700 ) {
1601
+ } else if (type == CMN_TYPE_XP && cmn -> part == PART_CMN700 ) {
1574
1602
hw -> wide_sel = true;
1575
1603
}
1576
1604
1577
1605
/* This is sufficiently annoying to recalculate, so cache it */
1578
- hw -> filter_sel = arm_cmn_filter_sel (cmn -> model , type , eventid );
1606
+ hw -> filter_sel = arm_cmn_filter_sel (cmn , type , eventid );
1579
1607
1580
1608
bynodeid = CMN_EVENT_BYNODEID (event );
1581
1609
nodeid = CMN_EVENT_NODEID (event );
@@ -2007,6 +2035,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
2007
2035
void __iomem * cfg_region ;
2008
2036
struct arm_cmn_node cfg , * dn ;
2009
2037
struct arm_cmn_dtm * dtm ;
2038
+ enum cmn_part part ;
2010
2039
u16 child_count , child_poff ;
2011
2040
u32 xp_offset [CMN_MAX_XPS ];
2012
2041
u64 reg ;
@@ -2018,7 +2047,19 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
2018
2047
return - ENODEV ;
2019
2048
2020
2049
cfg_region = cmn -> base + rgn_offset ;
2021
- reg = readl_relaxed (cfg_region + CMN_CFGM_PERIPH_ID_2 );
2050
+
2051
+ reg = readq_relaxed (cfg_region + CMN_CFGM_PERIPH_ID_01 );
2052
+ part = FIELD_GET (CMN_CFGM_PID0_PART_0 , reg );
2053
+ part |= FIELD_GET (CMN_CFGM_PID1_PART_1 , reg ) << 8 ;
2054
+ if (cmn -> part && cmn -> part != part )
2055
+ dev_warn (cmn -> dev ,
2056
+ "Firmware binding mismatch: expected part number 0x%x, found 0x%x\n" ,
2057
+ cmn -> part , part );
2058
+ cmn -> part = part ;
2059
+ if (!arm_cmn_model (cmn ))
2060
+ dev_warn (cmn -> dev , "Unknown part number: 0x%x\n" , part );
2061
+
2062
+ reg = readl_relaxed (cfg_region + CMN_CFGM_PERIPH_ID_23 );
2022
2063
cmn -> rev = FIELD_GET (CMN_CFGM_PID2_REVISION , reg );
2023
2064
2024
2065
reg = readq_relaxed (cfg_region + CMN_CFGM_INFO_GLOBAL );
@@ -2082,7 +2123,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
2082
2123
if (xp -> id == (1 << 3 ))
2083
2124
cmn -> mesh_x = xp -> logid ;
2084
2125
2085
- if (cmn -> model == CMN600 )
2126
+ if (cmn -> part == PART_CMN600 )
2086
2127
xp -> dtc = 0xf ;
2087
2128
else
2088
2129
xp -> dtc = 1 << readl_relaxed (xp_region + CMN_DTM_UNIT_INFO );
@@ -2202,7 +2243,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
2202
2243
if (cmn -> num_xps == 1 )
2203
2244
dev_warn (cmn -> dev , "1x1 config not fully supported, translate XP events manually\n" );
2204
2245
2205
- dev_dbg (cmn -> dev , "model %d, periph_id_2 revision %d\n" , cmn -> model , cmn -> rev );
2246
+ dev_dbg (cmn -> dev , "periph_id part 0x%03x revision %d\n" , cmn -> part , cmn -> rev );
2206
2247
reg = cmn -> ports_used ;
2207
2248
dev_dbg (cmn -> dev , "mesh %dx%d, ID width %d, ports %6pbl%s\n" ,
2208
2249
cmn -> mesh_x , cmn -> mesh_y , arm_cmn_xyidbits (cmn ), & reg ,
@@ -2257,17 +2298,17 @@ static int arm_cmn_probe(struct platform_device *pdev)
2257
2298
return - ENOMEM ;
2258
2299
2259
2300
cmn -> dev = & pdev -> dev ;
2260
- cmn -> model = (unsigned long )device_get_match_data (cmn -> dev );
2301
+ cmn -> part = (unsigned long )device_get_match_data (cmn -> dev );
2261
2302
platform_set_drvdata (pdev , cmn );
2262
2303
2263
- if (cmn -> model == CMN600 && has_acpi_companion (cmn -> dev )) {
2304
+ if (cmn -> part == PART_CMN600 && has_acpi_companion (cmn -> dev )) {
2264
2305
rootnode = arm_cmn600_acpi_probe (pdev , cmn );
2265
2306
} else {
2266
2307
rootnode = 0 ;
2267
2308
cmn -> base = devm_platform_ioremap_resource (pdev , 0 );
2268
2309
if (IS_ERR (cmn -> base ))
2269
2310
return PTR_ERR (cmn -> base );
2270
- if (cmn -> model == CMN600 )
2311
+ if (cmn -> part == PART_CMN600 )
2271
2312
rootnode = arm_cmn600_of_probe (pdev -> dev .of_node );
2272
2313
}
2273
2314
if (rootnode < 0 )
@@ -2336,20 +2377,20 @@ static int arm_cmn_remove(struct platform_device *pdev)
2336
2377
2337
2378
#ifdef CONFIG_OF
2338
2379
static const struct of_device_id arm_cmn_of_match [] = {
2339
- { .compatible = "arm,cmn-600" , .data = (void * )CMN600 },
2340
- { .compatible = "arm,cmn-650" , . data = ( void * ) CMN650 },
2341
- { .compatible = "arm,cmn-700" , . data = ( void * ) CMN700 },
2342
- { .compatible = "arm,ci-700" , . data = ( void * ) CI700 },
2380
+ { .compatible = "arm,cmn-600" , .data = (void * )PART_CMN600 },
2381
+ { .compatible = "arm,cmn-650" },
2382
+ { .compatible = "arm,cmn-700" },
2383
+ { .compatible = "arm,ci-700" },
2343
2384
{}
2344
2385
};
2345
2386
MODULE_DEVICE_TABLE (of , arm_cmn_of_match );
2346
2387
#endif
2347
2388
2348
2389
#ifdef CONFIG_ACPI
2349
2390
static const struct acpi_device_id arm_cmn_acpi_match [] = {
2350
- { "ARMHC600" , CMN600 },
2351
- { "ARMHC650" , CMN650 },
2352
- { "ARMHC700" , CMN700 },
2391
+ { "ARMHC600" , PART_CMN600 },
2392
+ { "ARMHC650" },
2393
+ { "ARMHC700" },
2353
2394
{}
2354
2395
};
2355
2396
MODULE_DEVICE_TABLE (acpi , arm_cmn_acpi_match );
0 commit comments