4444#define CMN_MAX_DTMS (CMN_MAX_XPS + (CMN_MAX_DIMENSION - 1) * 4)
4545
4646/* 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)
4952
5053#define CMN_CFGM_INFO_GLOBAL 0x900
5154#define CMN_INFO_MULTIPLE_DTM_EN BIT_ULL(63)
186189#define CMN_WP_DOWN 2
187190
188191
192+ /* Internal values for encoding event support */
189193enum cmn_model {
190194 CMN600 = 1 ,
191195 CMN650 = 2 ,
@@ -197,26 +201,34 @@ enum cmn_model {
197201 CMN_650ON = CMN650 | CMN700 ,
198202};
199203
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+
200212/* CMN-600 r0px shouldn't exist in silicon, thankfully */
201213enum 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 ,
220232};
221233
222234enum cmn_node_type {
@@ -306,7 +318,7 @@ struct arm_cmn {
306318 unsigned int state ;
307319
308320 enum cmn_revision rev ;
309- enum cmn_model model ;
321+ enum cmn_part part ;
310322 u8 mesh_x ;
311323 u8 mesh_y ;
312324 u16 num_xps ;
@@ -394,19 +406,35 @@ static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
394406 return NULL ;
395407}
396408
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+
397425static u32 arm_cmn_device_connect_info (const struct arm_cmn * cmn ,
398426 const struct arm_cmn_node * xp , int port )
399427{
400428 int offset = CMN_MXP__CONNECT_INFO (port );
401429
402430 if (port >= 2 ) {
403- if (cmn -> model & ( CMN600 | CMN650 ) )
431+ if (cmn -> part == PART_CMN600 || cmn -> part == PART_CMN650 )
404432 return 0 ;
405433 /*
406434 * CI-700 may have extra ports, but still has the
407435 * mesh_port_connect_info registers in the way.
408436 */
409- if (cmn -> model == CI700 )
437+ if (cmn -> part == PART_CI700 )
410438 offset += CI700_CONNECT_INFO_P2_5_OFFSET ;
411439 }
412440
@@ -640,7 +668,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
640668
641669 eattr = container_of (attr , typeof (* eattr ), attr .attr );
642670
643- if (!(eattr -> model & cmn -> model ))
671+ if (!(eattr -> model & arm_cmn_model ( cmn ) ))
644672 return 0 ;
645673
646674 type = eattr -> type ;
@@ -658,7 +686,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
658686 if ((intf & 4 ) && !(cmn -> ports_used & BIT (intf & 3 )))
659687 return 0 ;
660688
661- if (chan == 4 && cmn -> model == CMN600 )
689+ if (chan == 4 && cmn -> part == PART_CMN600 )
662690 return 0 ;
663691
664692 if ((chan == 5 && cmn -> rsp_vc_num < 2 ) ||
@@ -669,36 +697,36 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
669697 }
670698
671699 /* 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 ) {
674702 if (type == CMN_TYPE_CXRA && eventid > 0x10 )
675703 return 0 ;
676704 }
677- if (cmn -> rev < CMN600_R1P2 ) {
705+ if (cmn -> rev < REV_CMN600_R1P2 ) {
678706 if (type == CMN_TYPE_HNF && eventid == 0x1b )
679707 return 0 ;
680708 if (type == CMN_TYPE_CXRA || type == CMN_TYPE_CXHA )
681709 return 0 ;
682710 }
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 ) {
685713 if (type == CMN_TYPE_HNF && eventid > 0x22 )
686714 return 0 ;
687715 if (type == CMN_TYPE_SBSX && eventid == 0x17 )
688716 return 0 ;
689717 if (type == CMN_TYPE_RNI && eventid > 0x10 )
690718 return 0 ;
691719 }
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 ) {
694722 if (type == CMN_TYPE_HNF && eventid > 0x2c )
695723 return 0 ;
696724 if (type == CMN_TYPE_CCHA && eventid > 0x74 )
697725 return 0 ;
698726 if (type == CMN_TYPE_CCLA && eventid > 0x27 )
699727 return 0 ;
700728 }
701- if (cmn -> rev < CMN700_R1P0 ) {
729+ if (cmn -> rev < REV_CMN700_R1P0 ) {
702730 if (type == CMN_TYPE_HNF && eventid > 0x2b )
703731 return 0 ;
704732 }
@@ -1200,7 +1228,7 @@ static u32 arm_cmn_wp_config(struct perf_event *event)
12001228 u32 grp = CMN_EVENT_WP_GRP (event );
12011229 u32 exc = CMN_EVENT_WP_EXCLUSIVE (event );
12021230 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 ;
12041232
12051233 config = FIELD_PREP (CMN_DTM_WPn_CONFIG_WP_DEV_SEL , dev ) |
12061234 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)
15201548 return ret ;
15211549}
15221550
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 ,
15241552 enum cmn_node_type type ,
15251553 unsigned int eventid )
15261554{
15271555 struct arm_cmn_event_attr * e ;
1528- int i ;
1556+ enum cmn_model model = arm_cmn_model ( cmn ) ;
15291557
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 ++ ) {
15311559 e = container_of (arm_cmn_event_attrs [i ], typeof (* e ), attr .attr );
15321560 if (e -> model & model && e -> type == type && e -> eventid == eventid )
15331561 return e -> fsel ;
@@ -1570,12 +1598,12 @@ static int arm_cmn_event_init(struct perf_event *event)
15701598 /* ...but the DTM may depend on which port we're watching */
15711599 if (cmn -> multi_dtm )
15721600 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 ) {
15741602 hw -> wide_sel = true;
15751603 }
15761604
15771605 /* 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 );
15791607
15801608 bynodeid = CMN_EVENT_BYNODEID (event );
15811609 nodeid = CMN_EVENT_NODEID (event );
@@ -2007,6 +2035,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
20072035 void __iomem * cfg_region ;
20082036 struct arm_cmn_node cfg , * dn ;
20092037 struct arm_cmn_dtm * dtm ;
2038+ enum cmn_part part ;
20102039 u16 child_count , child_poff ;
20112040 u32 xp_offset [CMN_MAX_XPS ];
20122041 u64 reg ;
@@ -2018,7 +2047,19 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
20182047 return - ENODEV ;
20192048
20202049 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 );
20222063 cmn -> rev = FIELD_GET (CMN_CFGM_PID2_REVISION , reg );
20232064
20242065 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)
20822123 if (xp -> id == (1 << 3 ))
20832124 cmn -> mesh_x = xp -> logid ;
20842125
2085- if (cmn -> model == CMN600 )
2126+ if (cmn -> part == PART_CMN600 )
20862127 xp -> dtc = 0xf ;
20872128 else
20882129 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)
22022243 if (cmn -> num_xps == 1 )
22032244 dev_warn (cmn -> dev , "1x1 config not fully supported, translate XP events manually\n" );
22042245
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 );
22062247 reg = cmn -> ports_used ;
22072248 dev_dbg (cmn -> dev , "mesh %dx%d, ID width %d, ports %6pbl%s\n" ,
22082249 cmn -> mesh_x , cmn -> mesh_y , arm_cmn_xyidbits (cmn ), & reg ,
@@ -2257,17 +2298,17 @@ static int arm_cmn_probe(struct platform_device *pdev)
22572298 return - ENOMEM ;
22582299
22592300 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 );
22612302 platform_set_drvdata (pdev , cmn );
22622303
2263- if (cmn -> model == CMN600 && has_acpi_companion (cmn -> dev )) {
2304+ if (cmn -> part == PART_CMN600 && has_acpi_companion (cmn -> dev )) {
22642305 rootnode = arm_cmn600_acpi_probe (pdev , cmn );
22652306 } else {
22662307 rootnode = 0 ;
22672308 cmn -> base = devm_platform_ioremap_resource (pdev , 0 );
22682309 if (IS_ERR (cmn -> base ))
22692310 return PTR_ERR (cmn -> base );
2270- if (cmn -> model == CMN600 )
2311+ if (cmn -> part == PART_CMN600 )
22712312 rootnode = arm_cmn600_of_probe (pdev -> dev .of_node );
22722313 }
22732314 if (rootnode < 0 )
@@ -2336,20 +2377,20 @@ static int arm_cmn_remove(struct platform_device *pdev)
23362377
23372378#ifdef CONFIG_OF
23382379static 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" },
23432384 {}
23442385};
23452386MODULE_DEVICE_TABLE (of , arm_cmn_of_match );
23462387#endif
23472388
23482389#ifdef CONFIG_ACPI
23492390static 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" },
23532394 {}
23542395};
23552396MODULE_DEVICE_TABLE (acpi , arm_cmn_acpi_match );
0 commit comments