2121
2222DEFINE_CORESIGHT_DEVLIST (tpda_devs , "tpda" );
2323
24+ static bool coresight_device_is_tpdm (struct coresight_device * csdev )
25+ {
26+ return (csdev -> type == CORESIGHT_DEV_TYPE_SOURCE ) &&
27+ (csdev -> subtype .source_subtype ==
28+ CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM );
29+ }
30+
31+ /*
32+ * Read the DSB element size from the TPDM device
33+ * Returns
34+ * The dsb element size read from the devicetree if available.
35+ * 0 - Otherwise, with a warning once.
36+ */
37+ static int tpdm_read_dsb_element_size (struct coresight_device * csdev )
38+ {
39+ int rc = 0 ;
40+ u8 size = 0 ;
41+
42+ rc = fwnode_property_read_u8 (dev_fwnode (csdev -> dev .parent ),
43+ "qcom,dsb-element-size" , & size );
44+ if (rc )
45+ dev_warn_once (& csdev -> dev ,
46+ "Failed to read TPDM DSB Element size: %d\n" , rc );
47+
48+ return size ;
49+ }
50+
51+ /*
52+ * Search and read element data size from the TPDM node in
53+ * the devicetree. Each input port of TPDA is connected to
54+ * a TPDM. Different TPDM supports different types of dataset,
55+ * and some may support more than one type of dataset.
56+ * Parameter "inport" is used to pass in the input port number
57+ * of TPDA, and it is set to -1 in the recursize call.
58+ */
59+ static int tpda_get_element_size (struct coresight_device * csdev ,
60+ int inport )
61+ {
62+ int dsb_size = - ENOENT ;
63+ int i , size ;
64+ struct coresight_device * in ;
65+
66+ for (i = 0 ; i < csdev -> pdata -> nr_inconns ; i ++ ) {
67+ in = csdev -> pdata -> in_conns [i ]-> src_dev ;
68+ if (!in )
69+ continue ;
70+
71+ /* Ignore the paths that do not match port */
72+ if (inport > 0 &&
73+ csdev -> pdata -> in_conns [i ]-> dest_port != inport )
74+ continue ;
75+
76+ if (coresight_device_is_tpdm (in )) {
77+ size = tpdm_read_dsb_element_size (in );
78+ } else {
79+ /* Recurse down the path */
80+ size = tpda_get_element_size (in , -1 );
81+ }
82+
83+ if (size < 0 )
84+ return size ;
85+
86+ if (dsb_size < 0 ) {
87+ /* Found a size, save it. */
88+ dsb_size = size ;
89+ } else {
90+ /* Found duplicate TPDMs */
91+ return - EEXIST ;
92+ }
93+ }
94+
95+ return dsb_size ;
96+ }
97+
2498/* Settings pre enabling port control register */
2599static void tpda_enable_pre_port (struct tpda_drvdata * drvdata )
26100{
@@ -32,43 +106,75 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
32106 writel_relaxed (val , drvdata -> base + TPDA_CR );
33107}
34108
35- static void tpda_enable_port (struct tpda_drvdata * drvdata , int port )
109+ static int tpda_enable_port (struct tpda_drvdata * drvdata , int port )
36110{
37111 u32 val ;
112+ int size ;
38113
39114 val = readl_relaxed (drvdata -> base + TPDA_Pn_CR (port ));
115+ /*
116+ * Configure aggregator port n DSB data set element size
117+ * Set the bit to 0 if the size is 32
118+ * Set the bit to 1 if the size is 64
119+ */
120+ size = tpda_get_element_size (drvdata -> csdev , port );
121+ switch (size ) {
122+ case 32 :
123+ val &= ~TPDA_Pn_CR_DSBSIZE ;
124+ break ;
125+ case 64 :
126+ val |= TPDA_Pn_CR_DSBSIZE ;
127+ break ;
128+ case 0 :
129+ return - EEXIST ;
130+ case - EEXIST :
131+ dev_warn_once (& drvdata -> csdev -> dev ,
132+ "Detected multiple TPDMs on port %d" , - EEXIST );
133+ return - EEXIST ;
134+ default :
135+ return - EINVAL ;
136+ }
137+
40138 /* Enable the port */
41139 val |= TPDA_Pn_CR_ENA ;
42140 writel_relaxed (val , drvdata -> base + TPDA_Pn_CR (port ));
141+
142+ return 0 ;
43143}
44144
45- static void __tpda_enable (struct tpda_drvdata * drvdata , int port )
145+ static int __tpda_enable (struct tpda_drvdata * drvdata , int port )
46146{
147+ int ret ;
148+
47149 CS_UNLOCK (drvdata -> base );
48150
49151 if (!drvdata -> csdev -> enable )
50152 tpda_enable_pre_port (drvdata );
51153
52- tpda_enable_port (drvdata , port );
53-
154+ ret = tpda_enable_port (drvdata , port );
54155 CS_LOCK (drvdata -> base );
156+
157+ return ret ;
55158}
56159
57160static int tpda_enable (struct coresight_device * csdev ,
58161 struct coresight_connection * in ,
59162 struct coresight_connection * out )
60163{
61164 struct tpda_drvdata * drvdata = dev_get_drvdata (csdev -> dev .parent );
165+ int ret = 0 ;
62166
63167 spin_lock (& drvdata -> spinlock );
64- if (atomic_read (& in -> dest_refcnt ) == 0 )
65- __tpda_enable (drvdata , in -> dest_port );
168+ if (atomic_read (& in -> dest_refcnt ) == 0 ) {
169+ ret = __tpda_enable (drvdata , in -> dest_port );
170+ if (!ret ) {
171+ atomic_inc (& in -> dest_refcnt );
172+ dev_dbg (drvdata -> dev , "TPDA inport %d enabled.\n" , in -> dest_port );
173+ }
174+ }
66175
67- atomic_inc (& in -> dest_refcnt );
68176 spin_unlock (& drvdata -> spinlock );
69-
70- dev_dbg (drvdata -> dev , "TPDA inport %d enabled.\n" , in -> dest_port );
71- return 0 ;
177+ return ret ;
72178}
73179
74180static void __tpda_disable (struct tpda_drvdata * drvdata , int port )
0 commit comments