8
8
9
9
#include "coresight-cti.h"
10
10
11
+ /*
12
+ * Declare the number of static declared attribute groups
13
+ * Value includes groups + NULL value at end of table.
14
+ */
15
+ #define CORESIGHT_CTI_STATIC_GROUPS_MAX 5
16
+
17
+ /*
18
+ * List of trigger signal type names. Match the constants declared in
19
+ * include\dt-bindings\arm\coresight-cti-dt.h
20
+ */
21
+ static const char * const sig_type_names [] = {
22
+ "genio" , /* GEN_IO */
23
+ "intreq" , /* GEN_INTREQ */
24
+ "intack" , /* GEN_INTACK */
25
+ "haltreq" , /* GEN_HALTREQ */
26
+ "restartreq" , /* GEN_RESTARTREQ */
27
+ "pe_edbgreq" , /* PE_EDBGREQ */
28
+ "pe_dbgrestart" ,/* PE_DBGRESTART */
29
+ "pe_ctiirq" , /* PE_CTIIRQ */
30
+ "pe_pmuirq" , /* PE_PMUIRQ */
31
+ "pe_dbgtrigger" ,/* PE_DBGTRIGGER */
32
+ "etm_extout" , /* ETM_EXTOUT */
33
+ "etm_extin" , /* ETM_EXTIN */
34
+ "snk_full" , /* SNK_FULL */
35
+ "snk_acqcomp" , /* SNK_ACQCOMP */
36
+ "snk_flushcomp" ,/* SNK_FLUSHCOMP */
37
+ "snk_flushin" , /* SNK_FLUSHIN */
38
+ "snk_trigin" , /* SNK_TRIGIN */
39
+ "stm_asyncout" , /* STM_ASYNCOUT */
40
+ "stm_tout_spte" ,/* STM_TOUT_SPTE */
41
+ "stm_tout_sw" , /* STM_TOUT_SW */
42
+ "stm_tout_hete" ,/* STM_TOUT_HETE */
43
+ "stm_hwevent" , /* STM_HWEVENT */
44
+ "ela_tstart" , /* ELA_TSTART */
45
+ "ela_tstop" , /* ELA_TSTOP */
46
+ "ela_dbgreq" , /* ELA_DBGREQ */
47
+ };
48
+
49
+ /* Show function pointer used in the connections dynamic declared attributes*/
50
+ typedef ssize_t (* p_show_fn )(struct device * dev , struct device_attribute * attr ,
51
+ char * buf );
52
+
53
+ /* Connection attribute types */
54
+ enum cti_conn_attr_type {
55
+ CTI_CON_ATTR_NAME ,
56
+ CTI_CON_ATTR_TRIGIN_SIG ,
57
+ CTI_CON_ATTR_TRIGOUT_SIG ,
58
+ CTI_CON_ATTR_TRIGIN_TYPES ,
59
+ CTI_CON_ATTR_TRIGOUT_TYPES ,
60
+ CTI_CON_ATTR_MAX ,
61
+ };
62
+
63
+ /* Names for the connection attributes */
64
+ static const char * const con_attr_names [CTI_CON_ATTR_MAX ] = {
65
+ "name" ,
66
+ "in_signals" ,
67
+ "out_signals" ,
68
+ "in_types" ,
69
+ "out_types" ,
70
+ };
71
+
11
72
/* basic attributes */
12
73
static ssize_t enable_show (struct device * dev ,
13
74
struct device_attribute * attr ,
@@ -75,11 +136,22 @@ static ssize_t ctmid_show(struct device *dev,
75
136
}
76
137
static DEVICE_ATTR_RO (ctmid );
77
138
139
+ static ssize_t nr_trigger_cons_show (struct device * dev ,
140
+ struct device_attribute * attr ,
141
+ char * buf )
142
+ {
143
+ struct cti_drvdata * drvdata = dev_get_drvdata (dev -> parent );
144
+
145
+ return sprintf (buf , "%d\n" , drvdata -> ctidev .nr_trig_con );
146
+ }
147
+ static DEVICE_ATTR_RO (nr_trigger_cons );
148
+
78
149
/* attribute and group sysfs tables. */
79
150
static struct attribute * coresight_cti_attrs [] = {
80
151
& dev_attr_enable .attr ,
81
152
& dev_attr_powered .attr ,
82
153
& dev_attr_ctmid .attr ,
154
+ & dev_attr_nr_trigger_cons .attr ,
83
155
NULL ,
84
156
};
85
157
@@ -850,7 +922,261 @@ static struct attribute *coresight_cti_channel_attrs[] = {
850
922
NULL ,
851
923
};
852
924
853
- /* sysfs groups */
925
+ /* Create the connections trigger groups and attrs dynamically */
926
+ /*
927
+ * Each connection has dynamic group triggers<N> + name, trigin/out sigs/types
928
+ * attributes, + each device has static nr_trigger_cons giving the number
929
+ * of groups. e.g. in sysfs:-
930
+ * /cti_<name>/triggers0
931
+ * /cti_<name>/triggers1
932
+ * /cti_<name>/nr_trigger_cons
933
+ * where nr_trigger_cons = 2
934
+ */
935
+ static ssize_t con_name_show (struct device * dev ,
936
+ struct device_attribute * attr ,
937
+ char * buf )
938
+ {
939
+ struct dev_ext_attribute * ext_attr =
940
+ container_of (attr , struct dev_ext_attribute , attr );
941
+ struct cti_trig_con * con = (struct cti_trig_con * )ext_attr -> var ;
942
+
943
+ return sprintf (buf , "%s\n" , con -> con_dev_name );
944
+ }
945
+
946
+ static ssize_t trigin_sig_show (struct device * dev ,
947
+ struct device_attribute * attr ,
948
+ char * buf )
949
+ {
950
+ struct dev_ext_attribute * ext_attr =
951
+ container_of (attr , struct dev_ext_attribute , attr );
952
+ struct cti_trig_con * con = (struct cti_trig_con * )ext_attr -> var ;
953
+ struct cti_drvdata * drvdata = dev_get_drvdata (dev -> parent );
954
+ struct cti_config * cfg = & drvdata -> config ;
955
+ unsigned long mask = con -> con_in -> used_mask ;
956
+
957
+ return bitmap_print_to_pagebuf (true, buf , & mask , cfg -> nr_trig_max );
958
+ }
959
+
960
+ static ssize_t trigout_sig_show (struct device * dev ,
961
+ struct device_attribute * attr ,
962
+ char * buf )
963
+ {
964
+ struct dev_ext_attribute * ext_attr =
965
+ container_of (attr , struct dev_ext_attribute , attr );
966
+ struct cti_trig_con * con = (struct cti_trig_con * )ext_attr -> var ;
967
+ struct cti_drvdata * drvdata = dev_get_drvdata (dev -> parent );
968
+ struct cti_config * cfg = & drvdata -> config ;
969
+ unsigned long mask = con -> con_out -> used_mask ;
970
+
971
+ return bitmap_print_to_pagebuf (true, buf , & mask , cfg -> nr_trig_max );
972
+ }
973
+
974
+ /* convert a sig type id to a name */
975
+ static const char *
976
+ cti_sig_type_name (struct cti_trig_con * con , int used_count , bool in )
977
+ {
978
+ int idx = 0 ;
979
+ struct cti_trig_grp * grp = in ? con -> con_in : con -> con_out ;
980
+
981
+ if (used_count < grp -> nr_sigs )
982
+ idx = grp -> sig_types [used_count ];
983
+ return sig_type_names [idx ];
984
+ }
985
+
986
+ static ssize_t trigin_type_show (struct device * dev ,
987
+ struct device_attribute * attr ,
988
+ char * buf )
989
+ {
990
+ struct dev_ext_attribute * ext_attr =
991
+ container_of (attr , struct dev_ext_attribute , attr );
992
+ struct cti_trig_con * con = (struct cti_trig_con * )ext_attr -> var ;
993
+ int sig_idx , used = 0 ;
994
+ const char * name ;
995
+
996
+ for (sig_idx = 0 ; sig_idx < con -> con_in -> nr_sigs ; sig_idx ++ ) {
997
+ name = cti_sig_type_name (con , sig_idx , true);
998
+ used += sprintf (buf + used , "%s " , name );
999
+ }
1000
+ used += sprintf (buf + used , "\n" );
1001
+ return used ;
1002
+ }
1003
+
1004
+ static ssize_t trigout_type_show (struct device * dev ,
1005
+ struct device_attribute * attr ,
1006
+ char * buf )
1007
+ {
1008
+ struct dev_ext_attribute * ext_attr =
1009
+ container_of (attr , struct dev_ext_attribute , attr );
1010
+ struct cti_trig_con * con = (struct cti_trig_con * )ext_attr -> var ;
1011
+ int sig_idx , used = 0 ;
1012
+ const char * name ;
1013
+
1014
+ for (sig_idx = 0 ; sig_idx < con -> con_out -> nr_sigs ; sig_idx ++ ) {
1015
+ name = cti_sig_type_name (con , sig_idx , false);
1016
+ used += sprintf (buf + used , "%s " , name );
1017
+ }
1018
+ used += sprintf (buf + used , "\n" );
1019
+ return used ;
1020
+ }
1021
+
1022
+ /*
1023
+ * Array of show function names declared above to allow selection
1024
+ * for the connection attributes
1025
+ */
1026
+ static p_show_fn show_fns [CTI_CON_ATTR_MAX ] = {
1027
+ con_name_show ,
1028
+ trigin_sig_show ,
1029
+ trigout_sig_show ,
1030
+ trigin_type_show ,
1031
+ trigout_type_show ,
1032
+ };
1033
+
1034
+ static int cti_create_con_sysfs_attr (struct device * dev ,
1035
+ struct cti_trig_con * con ,
1036
+ enum cti_conn_attr_type attr_type ,
1037
+ int attr_idx )
1038
+ {
1039
+ struct dev_ext_attribute * eattr = 0 ;
1040
+ char * name = 0 ;
1041
+
1042
+ eattr = devm_kzalloc (dev , sizeof (struct dev_ext_attribute ),
1043
+ GFP_KERNEL );
1044
+ if (eattr ) {
1045
+ name = devm_kstrdup (dev , con_attr_names [attr_type ],
1046
+ GFP_KERNEL );
1047
+ if (name ) {
1048
+ /* fill out the underlying attribute struct */
1049
+ eattr -> attr .attr .name = name ;
1050
+ eattr -> attr .attr .mode = 0444 ;
1051
+
1052
+ /* now the device_attribute struct */
1053
+ eattr -> attr .show = show_fns [attr_type ];
1054
+ } else {
1055
+ return - ENOMEM ;
1056
+ }
1057
+ } else {
1058
+ return - ENOMEM ;
1059
+ }
1060
+ eattr -> var = con ;
1061
+ con -> con_attrs [attr_idx ] = & eattr -> attr .attr ;
1062
+ return 0 ;
1063
+ }
1064
+
1065
+ static struct attribute_group *
1066
+ cti_create_con_sysfs_group (struct device * dev , struct cti_device * ctidev ,
1067
+ int con_idx , struct cti_trig_con * tc )
1068
+ {
1069
+ struct attribute_group * group = NULL ;
1070
+ int grp_idx ;
1071
+
1072
+ group = devm_kzalloc (dev , sizeof (struct attribute_group ), GFP_KERNEL );
1073
+ if (!group )
1074
+ return NULL ;
1075
+
1076
+ group -> name = devm_kasprintf (dev , GFP_KERNEL , "triggers%d" , con_idx );
1077
+ if (!group -> name )
1078
+ return NULL ;
1079
+
1080
+ grp_idx = con_idx + CORESIGHT_CTI_STATIC_GROUPS_MAX - 1 ;
1081
+ ctidev -> con_groups [grp_idx ] = group ;
1082
+ tc -> attr_group = group ;
1083
+ return group ;
1084
+ }
1085
+
1086
+ /* create a triggers connection group and the attributes for that group */
1087
+ static int cti_create_con_attr_set (struct device * dev , int con_idx ,
1088
+ struct cti_device * ctidev ,
1089
+ struct cti_trig_con * tc )
1090
+ {
1091
+ struct attribute_group * attr_group = NULL ;
1092
+ int attr_idx = 0 ;
1093
+ int err = - ENOMEM ;
1094
+
1095
+ attr_group = cti_create_con_sysfs_group (dev , ctidev , con_idx , tc );
1096
+ if (!attr_group )
1097
+ return - ENOMEM ;
1098
+
1099
+ /* allocate NULL terminated array of attributes */
1100
+ tc -> con_attrs = devm_kcalloc (dev , CTI_CON_ATTR_MAX + 1 ,
1101
+ sizeof (struct attribute * ), GFP_KERNEL );
1102
+ if (!tc -> con_attrs )
1103
+ return - ENOMEM ;
1104
+
1105
+ err = cti_create_con_sysfs_attr (dev , tc , CTI_CON_ATTR_NAME ,
1106
+ attr_idx ++ );
1107
+ if (err )
1108
+ return err ;
1109
+
1110
+ if (tc -> con_in -> nr_sigs > 0 ) {
1111
+ err = cti_create_con_sysfs_attr (dev , tc ,
1112
+ CTI_CON_ATTR_TRIGIN_SIG ,
1113
+ attr_idx ++ );
1114
+ if (err )
1115
+ return err ;
1116
+
1117
+ err = cti_create_con_sysfs_attr (dev , tc ,
1118
+ CTI_CON_ATTR_TRIGIN_TYPES ,
1119
+ attr_idx ++ );
1120
+ if (err )
1121
+ return err ;
1122
+ }
1123
+
1124
+ if (tc -> con_out -> nr_sigs > 0 ) {
1125
+ err = cti_create_con_sysfs_attr (dev , tc ,
1126
+ CTI_CON_ATTR_TRIGOUT_SIG ,
1127
+ attr_idx ++ );
1128
+ if (err )
1129
+ return err ;
1130
+
1131
+ err = cti_create_con_sysfs_attr (dev , tc ,
1132
+ CTI_CON_ATTR_TRIGOUT_TYPES ,
1133
+ attr_idx ++ );
1134
+ if (err )
1135
+ return err ;
1136
+ }
1137
+ attr_group -> attrs = tc -> con_attrs ;
1138
+ return 0 ;
1139
+ }
1140
+
1141
+ /* create the array of group pointers for the CTI sysfs groups */
1142
+ int cti_create_cons_groups (struct device * dev , struct cti_device * ctidev )
1143
+ {
1144
+ int nr_groups ;
1145
+
1146
+ /* nr groups = dynamic + static + NULL terminator */
1147
+ nr_groups = ctidev -> nr_trig_con + CORESIGHT_CTI_STATIC_GROUPS_MAX ;
1148
+ ctidev -> con_groups = devm_kcalloc (dev , nr_groups ,
1149
+ sizeof (struct attribute_group * ),
1150
+ GFP_KERNEL );
1151
+ if (!ctidev -> con_groups )
1152
+ return - ENOMEM ;
1153
+ return 0 ;
1154
+ }
1155
+
1156
+ int cti_create_cons_sysfs (struct device * dev , struct cti_drvdata * drvdata )
1157
+ {
1158
+ struct cti_device * ctidev = & drvdata -> ctidev ;
1159
+ int err = 0 , con_idx = 0 , i ;
1160
+ struct cti_trig_con * tc = NULL ;
1161
+
1162
+ err = cti_create_cons_groups (dev , ctidev );
1163
+ if (err )
1164
+ return err ;
1165
+
1166
+ /* populate first locations with the static set of groups */
1167
+ for (i = 0 ; i < (CORESIGHT_CTI_STATIC_GROUPS_MAX - 1 ); i ++ )
1168
+ ctidev -> con_groups [i ] = coresight_cti_groups [i ];
1169
+
1170
+ /* add dynamic set for each connection */
1171
+ list_for_each_entry (tc , & ctidev -> trig_cons , node ) {
1172
+ err = cti_create_con_attr_set (dev , con_idx ++ , ctidev , tc );
1173
+ if (err )
1174
+ break ;
1175
+ }
1176
+ return err ;
1177
+ }
1178
+
1179
+ /* attribute and group sysfs tables. */
854
1180
static const struct attribute_group coresight_cti_group = {
855
1181
.attrs = coresight_cti_attrs ,
856
1182
};
@@ -870,7 +1196,8 @@ static const struct attribute_group coresight_cti_channels_group = {
870
1196
.name = "channels" ,
871
1197
};
872
1198
873
- const struct attribute_group * coresight_cti_groups [] = {
1199
+ const struct attribute_group *
1200
+ coresight_cti_groups [CORESIGHT_CTI_STATIC_GROUPS_MAX ] = {
874
1201
& coresight_cti_group ,
875
1202
& coresight_cti_mgmt_group ,
876
1203
& coresight_cti_regs_group ,
0 commit comments