xref: /OK3568_Linux_fs/kernel/drivers/hwtracing/coresight/mali/sources/ela/coresight_mali_source_ela_core.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3  *
4  * (C) COPYRIGHT 2022 ARM Limited. All rights reserved.
5  *
6  * This program is free software and is provided to you under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation, and any use by you of this program is subject to the terms
9  * of such GNU license.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you can access it online at
18  * http://www.gnu.org/licenses/gpl-2.0.html.
19  *
20  */
21 
22 #include <linux/of_platform.h>
23 #include <coresight-priv.h>
24 #include "sources/coresight_mali_sources.h"
25 #include "coresight-ela600.h"
26 
27 /* Linux Coresight framework does not support multiple sources enabled
28  * at the same time.
29  *
30  * To avoid Kernel instability, all Mali Coresight sources use the
31  * same trace ID value as the mandatory ETM one.
32  */
33 #define CS_MALI_TRACE_ID 0x00000010
34 
35 #define CS_ELA_BASE_ADDR 0xE0043000
36 #define CS_GPU_COMMAND_ADDR 0x40003030
37 #define CS_GPU_COMMAND_TRACE_CONTROL_EN 0x000001DC
38 #define CS_ELA_MAX_SIGNAL_GROUPS 12U
39 #define CS_SG_NAME_MAX_LEN 10U
40 #define CS_ELA_NR_SIG_REGS 8U
41 
42 #define NELEMS(s) (sizeof(s) / sizeof((s)[0]))
43 
44 #define CS_ELA_SIGREGS_ATTR_RW(_a, _b)                                                             \
45 	static ssize_t _a##_show(struct device *dev, struct device_attribute *attr,                \
46 				 char *const buf)                                                  \
47 	{                                                                                          \
48 		return sprintf_regs(buf, CS_ELA_##_b##_0, CS_ELA_##_b##_7);                        \
49 	}                                                                                          \
50 	static ssize_t _a##_store(struct device *dev, struct device_attribute *attr,               \
51 				  const char *buf, size_t count)                                   \
52 	{                                                                                          \
53 		return verify_store_8_regs(dev, buf, count, CS_ELA_##_b##_0);                      \
54 	}                                                                                          \
55 	static DEVICE_ATTR_RW(_a)
56 
57 enum cs_ela_dynamic_regs {
58 	CS_ELA_TIMECTRL,
59 	CS_ELA_TSSR,
60 
61 	CS_ELA_SIGSEL0,
62 	CS_ELA_COMPCTRL0,
63 	CS_ELA_ALTCOMPCTRL0,
64 	CS_ELA_TWBSEL0,
65 	CS_ELA_QUALMASK0,
66 	CS_ELA_QUALCOMP0,
67 	CS_ELA_SIGMASK0_0,
68 	CS_ELA_SIGMASK0_1,
69 	CS_ELA_SIGMASK0_2,
70 	CS_ELA_SIGMASK0_3,
71 	CS_ELA_SIGMASK0_4,
72 	CS_ELA_SIGMASK0_5,
73 	CS_ELA_SIGMASK0_6,
74 	CS_ELA_SIGMASK0_7,
75 	CS_ELA_SIGCOMP0_0,
76 	CS_ELA_SIGCOMP0_1,
77 	CS_ELA_SIGCOMP0_2,
78 	CS_ELA_SIGCOMP0_3,
79 	CS_ELA_SIGCOMP0_4,
80 	CS_ELA_SIGCOMP0_5,
81 	CS_ELA_SIGCOMP0_6,
82 	CS_ELA_SIGCOMP0_7,
83 
84 	CS_ELA_SIGSEL4,
85 	CS_ELA_NEXTSTATE4,
86 	CS_ELA_ACTION4,
87 	CS_ELA_ALTNEXTSTATE4,
88 	CS_ELA_COMPCTRL4,
89 	CS_ELA_TWBSEL4,
90 	CS_ELA_SIGMASK4_0,
91 	CS_ELA_SIGMASK4_1,
92 	CS_ELA_SIGMASK4_2,
93 	CS_ELA_SIGMASK4_3,
94 	CS_ELA_SIGMASK4_4,
95 	CS_ELA_SIGMASK4_5,
96 	CS_ELA_SIGMASK4_6,
97 	CS_ELA_SIGMASK4_7,
98 	CS_ELA_SIGCOMP4_0,
99 	CS_ELA_SIGCOMP4_1,
100 	CS_ELA_SIGCOMP4_2,
101 	CS_ELA_SIGCOMP4_3,
102 	CS_ELA_SIGCOMP4_4,
103 	CS_ELA_SIGCOMP4_5,
104 	CS_ELA_SIGCOMP4_6,
105 	CS_ELA_SIGCOMP4_7,
106 
107 	CS_ELA_NR_DYN_REGS
108 };
109 
110 enum cs_ela_tracemodes {
111 	CS_ELA_TRACEMODE_NONE,
112 	CS_ELA_TRACEMODE_JCN,
113 	CS_ELA_TRACEMODE_CEU_EXEC,
114 	CS_ELA_TRACEMODE_CEU_CMDS,
115 	CS_ELA_TRACEMODE_MCU_AHBP,
116 	CS_ELA_TRACEMODE_HOST_AXI,
117 	CS_ELA_NR_TRACEMODE
118 };
119 
120 enum cs_ela_signal_types {
121 	CS_ELA_SIGTYPE_JCN_REQ,
122 	CS_ELA_SIGTYPE_JCN_RES,
123 	CS_ELA_SIGTYPE_CEU_EXEC,
124 	CS_ELA_SIGTYPE_CEU_CMDS,
125 	CS_ELA_SIGTYPE_MCU_AHBP,
126 	CS_ELA_SIGTYPE_HOST_AXI,
127 	CS_ELA_NR_SIGTYPE,
128 };
129 
130 struct cs_ela_state {
131 	enum cs_ela_tracemodes tracemode;
132 	u32 supported_tracemodes;
133 	int enabled;
134 	u32 signal_types[CS_ELA_NR_SIGTYPE];
135 	u32 regs[CS_ELA_NR_DYN_REGS];
136 };
137 
138 #if KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE
139 static char *type_name = "mali-source-ela";
140 #endif
141 
142 static struct cs_ela_state ela_state = { 0 };
143 
144 /* Setup ELA sysfs attributes */
145 static char *tracemode_names[] = {
146 	[CS_ELA_TRACEMODE_NONE] = "NONE",	  [CS_ELA_TRACEMODE_JCN] = "JCN",
147 	[CS_ELA_TRACEMODE_CEU_EXEC] = "CEU_EXEC", [CS_ELA_TRACEMODE_CEU_CMDS] = "CEU_CMDS",
148 	[CS_ELA_TRACEMODE_MCU_AHBP] = "MCU_AHBP", [CS_ELA_TRACEMODE_HOST_AXI] = "HOST_AXI",
149 };
150 
151 static char *signal_type_names[] = {
152 	[CS_ELA_SIGTYPE_JCN_REQ] = "jcn-request",    [CS_ELA_SIGTYPE_JCN_RES] = "jcn-response",
153 	[CS_ELA_SIGTYPE_CEU_EXEC] = "ceu-execution", [CS_ELA_SIGTYPE_CEU_CMDS] = "ceu-commands",
154 	[CS_ELA_SIGTYPE_MCU_AHBP] = "mcu-ahbp",	     [CS_ELA_SIGTYPE_HOST_AXI] = "host-axi",
155 };
156 
157 static int signal_type_tracemode_map[] = {
158 	[CS_ELA_SIGTYPE_JCN_REQ] = CS_ELA_TRACEMODE_JCN,
159 	[CS_ELA_SIGTYPE_JCN_RES] = CS_ELA_TRACEMODE_JCN,
160 	[CS_ELA_SIGTYPE_CEU_EXEC] = CS_ELA_TRACEMODE_CEU_EXEC,
161 	[CS_ELA_SIGTYPE_CEU_CMDS] = CS_ELA_TRACEMODE_CEU_CMDS,
162 	[CS_ELA_SIGTYPE_MCU_AHBP] = CS_ELA_TRACEMODE_MCU_AHBP,
163 	[CS_ELA_SIGTYPE_HOST_AXI] = CS_ELA_TRACEMODE_HOST_AXI,
164 };
165 
setup_tracemode_registers(int tracemode)166 static void setup_tracemode_registers(int tracemode)
167 {
168 	switch (tracemode) {
169 	case CS_ELA_TRACEMODE_NONE:
170 		/* Perform full reset of all dynamic registers */
171 		memset(ela_state.regs, 0x00000000, sizeof(u32) * CS_ELA_NR_DYN_REGS);
172 
173 		ela_state.tracemode = CS_ELA_TRACEMODE_NONE;
174 		break;
175 	case CS_ELA_TRACEMODE_JCN:
176 
177 		if (ela_state.signal_types[CS_ELA_SIGTYPE_JCN_REQ] ==
178 		    ela_state.signal_types[CS_ELA_SIGTYPE_JCN_RES]) {
179 			ela_state.regs[CS_ELA_TSSR] = 0x00000000;
180 
181 			ela_state.regs[CS_ELA_SIGSEL0] =
182 				ela_state.signal_types[CS_ELA_SIGTYPE_JCN_REQ];
183 
184 			ela_state.regs[CS_ELA_COMPCTRL0] = 0x00000010;
185 			ela_state.regs[CS_ELA_ALTCOMPCTRL0] = 0x00001000;
186 			ela_state.regs[CS_ELA_TWBSEL0] = 0x0000FFFF;
187 			ela_state.regs[CS_ELA_QUALMASK0] = 0x00000000;
188 			ela_state.regs[CS_ELA_QUALCOMP0] = 0x00000000;
189 
190 			memset(&ela_state.regs[CS_ELA_SIGMASK0_0], 0x00000000,
191 			       sizeof(u32) * (CS_ELA_SIGCOMP0_7 - CS_ELA_SIGMASK0_0 + 1));
192 			ela_state.regs[CS_ELA_SIGMASK0_1] = 0x80000000;
193 			ela_state.regs[CS_ELA_SIGMASK0_3] = 0x80000000;
194 			ela_state.regs[CS_ELA_SIGCOMP0_1] = 0x80000000;
195 			ela_state.regs[CS_ELA_SIGCOMP0_3] = 0x80000000;
196 
197 			memset(&ela_state.regs[CS_ELA_SIGSEL4], 0x00000000,
198 			       sizeof(u32) * (CS_ELA_SIGCOMP4_7 - CS_ELA_SIGSEL4 + 1));
199 
200 			ela_state.regs[CS_ELA_COMPCTRL4] = 0x11111111;
201 
202 		} else {
203 			ela_state.regs[CS_ELA_TSSR] = 0x00000010;
204 
205 			ela_state.regs[CS_ELA_SIGSEL0] =
206 				ela_state.signal_types[CS_ELA_SIGTYPE_JCN_REQ];
207 
208 			ela_state.regs[CS_ELA_COMPCTRL0] = 0x00000100;
209 			ela_state.regs[CS_ELA_ALTCOMPCTRL0] = 0x11111111;
210 			ela_state.regs[CS_ELA_TWBSEL0] = 0x00000FFF;
211 			ela_state.regs[CS_ELA_QUALMASK0] = 0x00000000;
212 			ela_state.regs[CS_ELA_QUALCOMP0] = 0x00000000;
213 
214 			memset(&ela_state.regs[CS_ELA_SIGMASK0_0], 0x00000000,
215 			       sizeof(u32) * (CS_ELA_SIGCOMP0_7 - CS_ELA_SIGMASK0_0 + 1));
216 			ela_state.regs[CS_ELA_SIGMASK0_2] |= 0x80000000;
217 			ela_state.regs[CS_ELA_SIGCOMP0_2] |= 0x80000000;
218 
219 			ela_state.regs[CS_ELA_SIGSEL4] =
220 				ela_state.signal_types[CS_ELA_SIGTYPE_JCN_RES];
221 			ela_state.regs[CS_ELA_NEXTSTATE4] = 0x00000010;
222 			ela_state.regs[CS_ELA_ACTION4] = 0x00000008;
223 			ela_state.regs[CS_ELA_ALTNEXTSTATE4] = 0x00000001;
224 			ela_state.regs[CS_ELA_COMPCTRL4] = 0x00000100;
225 			ela_state.regs[CS_ELA_TWBSEL4] = 0x00000FFF;
226 
227 			memset(&ela_state.regs[CS_ELA_SIGMASK4_0], 0x00000000,
228 			       sizeof(u32) * (CS_ELA_SIGCOMP4_7 - CS_ELA_SIGMASK4_0 + 1));
229 			ela_state.regs[CS_ELA_SIGMASK4_2] |= 0x80000000;
230 			ela_state.regs[CS_ELA_SIGCOMP4_2] |= 0x80000000;
231 		}
232 
233 		break;
234 	case CS_ELA_TRACEMODE_CEU_EXEC:
235 	case CS_ELA_TRACEMODE_CEU_CMDS:
236 		ela_state.regs[CS_ELA_TSSR] = 0x00000000;
237 
238 		if (tracemode == CS_ELA_TRACEMODE_CEU_EXEC) {
239 			ela_state.regs[CS_ELA_SIGSEL0] =
240 				ela_state.signal_types[CS_ELA_SIGTYPE_CEU_EXEC];
241 			ela_state.regs[CS_ELA_ALTCOMPCTRL0] = 0x00001000;
242 		} else if (tracemode == CS_ELA_TRACEMODE_CEU_CMDS) {
243 			ela_state.regs[CS_ELA_SIGSEL0] =
244 				ela_state.signal_types[CS_ELA_SIGTYPE_CEU_CMDS];
245 			ela_state.regs[CS_ELA_ALTCOMPCTRL0] = 0x11111111;
246 		}
247 
248 		ela_state.regs[CS_ELA_COMPCTRL0] = 0x00000001;
249 		ela_state.regs[CS_ELA_TWBSEL0] = 0x0000FFFF;
250 		ela_state.regs[CS_ELA_QUALMASK0] = 0x0000000F;
251 		ela_state.regs[CS_ELA_QUALCOMP0] = 0x0000000F;
252 
253 		memset(&ela_state.regs[CS_ELA_SIGMASK0_0], 0x00000000,
254 		       sizeof(u32) * (CS_ELA_SIGCOMP0_7 - CS_ELA_SIGMASK0_0 + 1));
255 
256 		memset(&ela_state.regs[CS_ELA_SIGSEL4], 0x00000000,
257 		       sizeof(u32) * (CS_ELA_SIGCOMP4_7 - CS_ELA_SIGSEL4 + 1));
258 
259 		ela_state.regs[CS_ELA_COMPCTRL4] = 0x11111111;
260 
261 		break;
262 	case CS_ELA_TRACEMODE_MCU_AHBP:
263 	case CS_ELA_TRACEMODE_HOST_AXI:
264 		ela_state.regs[CS_ELA_TSSR] = 0x00000000;
265 
266 		if (tracemode == CS_ELA_TRACEMODE_MCU_AHBP)
267 			ela_state.regs[CS_ELA_SIGSEL0] =
268 				ela_state.signal_types[CS_ELA_SIGTYPE_MCU_AHBP];
269 		else if (tracemode == CS_ELA_TRACEMODE_HOST_AXI)
270 			ela_state.regs[CS_ELA_SIGSEL0] =
271 				ela_state.signal_types[CS_ELA_SIGTYPE_HOST_AXI];
272 
273 		ela_state.regs[CS_ELA_COMPCTRL0] = 0x00000001;
274 		ela_state.regs[CS_ELA_ALTCOMPCTRL0] = 0x11111111;
275 		ela_state.regs[CS_ELA_TWBSEL0] = 0x000000FF;
276 		ela_state.regs[CS_ELA_QUALMASK0] = 0x00000003;
277 		ela_state.regs[CS_ELA_QUALCOMP0] = 0x00000003;
278 
279 		memset(&ela_state.regs[CS_ELA_SIGMASK0_0], 0x00000000,
280 		       sizeof(u32) * (CS_ELA_SIGCOMP0_7 - CS_ELA_SIGMASK0_0 + 1));
281 
282 		memset(&ela_state.regs[CS_ELA_SIGSEL4], 0x00000000,
283 		       sizeof(u32) * (CS_ELA_SIGCOMP4_7 - CS_ELA_SIGSEL4 + 1));
284 
285 		ela_state.regs[CS_ELA_COMPCTRL4] = 0x11111111;
286 
287 		break;
288 	}
289 	ela_state.tracemode = tracemode;
290 }
291 
select_show(struct device * dev,struct device_attribute * attr,char * const buf)292 static ssize_t select_show(struct device *dev, struct device_attribute *attr, char *const buf)
293 {
294 	ssize_t ret = 0;
295 	unsigned int mode;
296 
297 	for (mode = CS_ELA_TRACEMODE_NONE; mode < CS_ELA_NR_TRACEMODE; mode++) {
298 		if (ela_state.supported_tracemodes & (1U << mode)) {
299 			if (ela_state.tracemode == mode)
300 				ret += sprintf(buf + ret, "[%s]\n", tracemode_names[mode]);
301 			else
302 				ret += sprintf(buf + ret, "%s\n", tracemode_names[mode]);
303 		}
304 	}
305 	return ret;
306 }
307 
select_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)308 static ssize_t select_store(struct device *dev, struct device_attribute *attr, const char *buf,
309 			    size_t count)
310 {
311 	struct coresight_mali_source_drvdata *drvdata = dev_get_drvdata(dev->parent);
312 	unsigned int mode = 0;
313 
314 	/* Check if enabled and return error */
315 	if (ela_state.enabled == 1) {
316 		dev_err(drvdata->base.dev,
317 			"Config needs to be disabled before modifying registers");
318 		return -EINVAL;
319 	}
320 
321 	for (mode = CS_ELA_TRACEMODE_NONE; mode < CS_ELA_NR_TRACEMODE; mode++) {
322 		if (sysfs_streq(tracemode_names[mode], buf) &&
323 		    (ela_state.supported_tracemodes & (1U << mode))) {
324 			setup_tracemode_registers(mode);
325 			return count;
326 		}
327 	}
328 
329 	dev_err(drvdata->base.dev, "Invalid tracemode: %s", buf);
330 	return -EINVAL;
331 }
332 
333 static DEVICE_ATTR_RW(select);
334 
is_enabled_show(struct device * dev,struct device_attribute * attr,char * const buf)335 static ssize_t is_enabled_show(struct device *dev, struct device_attribute *attr, char *const buf)
336 {
337 	return sprintf(buf, "%d\n", ela_state.enabled);
338 }
339 
340 static DEVICE_ATTR_RO(is_enabled);
341 
sprintf_regs(char * const buf,int from_reg,int to_reg)342 static ssize_t sprintf_regs(char *const buf, int from_reg, int to_reg)
343 {
344 	ssize_t ret = 0;
345 	unsigned int i = 0;
346 
347 	for (i = from_reg; i <= to_reg; i++)
348 		ret += sprintf(buf + ret, "0x%08X ", ela_state.regs[i]);
349 
350 	ret += sprintf(buf + ret, "\n");
351 	return ret;
352 }
353 
verify_store_8_regs(struct device * dev,const char * buf,size_t count,int from_reg)354 static ssize_t verify_store_8_regs(struct device *dev, const char *buf, size_t count, int from_reg)
355 {
356 	struct coresight_mali_source_drvdata *drvdata = dev_get_drvdata(dev->parent);
357 	u32 regs[CS_ELA_NR_SIG_REGS] = { 0 };
358 	int items;
359 	unsigned int i;
360 
361 	if (ela_state.enabled == 1) {
362 		dev_err(drvdata->base.dev,
363 			"Config needs to be disabled before modifying registers");
364 		return -EINVAL;
365 	}
366 
367 	items = sscanf(buf, "%x %x %x %x %x %x %x %x", &regs[0], &regs[1], &regs[2], &regs[3],
368 		       &regs[4], &regs[5], &regs[6], &regs[7]);
369 	if (items <= 0) {
370 		dev_err(drvdata->base.dev, "Invalid register value");
371 		return -EINVAL;
372 	}
373 	if (items != CS_ELA_NR_SIG_REGS) {
374 		dev_err(drvdata->base.dev, "Incorrect number of registers set (%d != %d)", items,
375 			CS_ELA_NR_SIG_REGS);
376 		return -EINVAL;
377 	}
378 	for (i = 0; i < CS_ELA_NR_SIG_REGS; i++)
379 		ela_state.regs[from_reg + i] = regs[i];
380 
381 	return count;
382 }
383 
384 CS_ELA_SIGREGS_ATTR_RW(sigmask0, SIGMASK0);
385 CS_ELA_SIGREGS_ATTR_RW(sigcomp0, SIGCOMP0);
386 CS_ELA_SIGREGS_ATTR_RW(sigmask4, SIGMASK4);
387 CS_ELA_SIGREGS_ATTR_RW(sigcomp4, SIGCOMP4);
388 
389 static struct attribute *coresight_ela_attrs[] = {
390 	&dev_attr_select.attr,
391 	&dev_attr_is_enabled.attr,
392 	&dev_attr_sigmask0.attr,
393 	&dev_attr_sigcomp0.attr,
394 	&dev_attr_sigmask4.attr,
395 	&dev_attr_sigcomp4.attr,
396 	NULL,
397 };
398 
399 static struct attribute_group coresight_ela_group = {
400 	.attrs = coresight_ela_attrs,
401 };
402 
403 static const struct attribute_group *coresight_ela_groups[] = {
404 	&coresight_ela_group,
405 	NULL,
406 };
407 
coresight_mali_source_groups_get(void)408 const struct attribute_group **coresight_mali_source_groups_get(void)
409 {
410 	return coresight_ela_groups;
411 }
412 
413 /* Initialize ELA coresight driver */
414 
415 static struct kbase_debug_coresight_csf_address_range ela_range[] = {
416 	{ CS_ELA_BASE_ADDR, CS_ELA_BASE_ADDR + CORESIGHT_DEVTYPE },
417 	{ CS_GPU_COMMAND_ADDR, CS_GPU_COMMAND_ADDR }
418 };
419 
420 static struct kbase_debug_coresight_csf_op ela_enable_ops[] = {
421 	/* Clearing CTRL.RUN and the read only CTRL.TRACE_BUSY. */
422 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_CTRL, 0x00000000),
423 	/* Poll CTRL.TRACE_BUSY until it becomes low to ensure that trace has stopped. */
424 	POLL_OP(CS_ELA_BASE_ADDR + ELA_CTRL, ELA_CTRL_TRACE_BUSY, 0x0),
425 	/* 0 for now. TSEN = 1 or TSINT = 8 in future */
426 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_TIMECTRL, &ela_state.regs[CS_ELA_TIMECTRL]),
427 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_TSSR, &ela_state.regs[CS_ELA_TSSR]),
428 	/* ATID[6:0] = 4; valid range 0x1-0x6F, value must be unique and needs to be
429 	 * known for trace extraction
430 	 */
431 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_ATBCTRL, 0x00000400),
432 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_PTACTION, ELA_ACTION_TRACE),
433 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_AUXCTRL, 0x00000000),
434 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_CNTSEL, 0x00000000),
435 
436 	/* Trigger State 0 */
437 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGSEL(0), &ela_state.regs[CS_ELA_SIGSEL0]),
438 	/* May need to be configurable in future. */
439 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_TRIGCTRL(0), 0x00000000),
440 
441 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_NEXTSTATE(0), 0x00000001),
442 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_ACTION(0), ELA_ACTION_TRACE),
443 
444 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_ALTNEXTSTATE(0), 0x00000001),
445 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_ALTACTION(0), ELA_ACTION_TRACE),
446 
447 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_COMPCTRL(0), &ela_state.regs[CS_ELA_COMPCTRL0]),
448 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_ALTCOMPCTRL(0), &ela_state.regs[CS_ELA_ALTCOMPCTRL0]),
449 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_COUNTCOMP(0), 0x00000000),
450 
451 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_TWBSEL(0), &ela_state.regs[CS_ELA_TWBSEL0]),
452 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_EXTMASK(0), 0x00000000),
453 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_EXTCOMP(0), 0x00000000),
454 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_QUALMASK(0), &ela_state.regs[CS_ELA_QUALMASK0]),
455 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_QUALCOMP(0), &ela_state.regs[CS_ELA_QUALCOMP0]),
456 
457 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(0, 0), &ela_state.regs[CS_ELA_SIGMASK0_0]),
458 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(0, 1), &ela_state.regs[CS_ELA_SIGMASK0_1]),
459 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(0, 2), &ela_state.regs[CS_ELA_SIGMASK0_2]),
460 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(0, 3), &ela_state.regs[CS_ELA_SIGMASK0_3]),
461 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(0, 4), &ela_state.regs[CS_ELA_SIGMASK0_4]),
462 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(0, 5), &ela_state.regs[CS_ELA_SIGMASK0_5]),
463 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(0, 6), &ela_state.regs[CS_ELA_SIGMASK0_6]),
464 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(0, 7), &ela_state.regs[CS_ELA_SIGMASK0_7]),
465 
466 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(0, 0), &ela_state.regs[CS_ELA_SIGCOMP0_0]),
467 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(0, 1), &ela_state.regs[CS_ELA_SIGCOMP0_1]),
468 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(0, 2), &ela_state.regs[CS_ELA_SIGCOMP0_2]),
469 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(0, 3), &ela_state.regs[CS_ELA_SIGCOMP0_3]),
470 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(0, 4), &ela_state.regs[CS_ELA_SIGCOMP0_4]),
471 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(0, 5), &ela_state.regs[CS_ELA_SIGCOMP0_5]),
472 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(0, 6), &ela_state.regs[CS_ELA_SIGCOMP0_6]),
473 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(0, 7), &ela_state.regs[CS_ELA_SIGCOMP0_7]),
474 
475 	WRITE_RANGE_OP(CS_ELA_BASE_ADDR + ELA_SIGSEL(1), CS_ELA_BASE_ADDR + ELA_SIGCOMP(1, 7),
476 		       0x00000000),
477 	WRITE_RANGE_OP(CS_ELA_BASE_ADDR + ELA_SIGSEL(2), CS_ELA_BASE_ADDR + ELA_SIGCOMP(2, 7),
478 		       0x00000000),
479 	WRITE_RANGE_OP(CS_ELA_BASE_ADDR + ELA_SIGSEL(3), CS_ELA_BASE_ADDR + ELA_SIGCOMP(3, 7),
480 		       0x00000000),
481 
482 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_COMPCTRL(1), 0x11111111),
483 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_COMPCTRL(2), 0x11111111),
484 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_COMPCTRL(3), 0x11111111),
485 
486 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_ALTCOMPCTRL(1), 0x11111111),
487 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_ALTCOMPCTRL(2), 0x11111111),
488 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_ALTCOMPCTRL(3), 0x11111111),
489 
490 	/* Trigger State 4 */
491 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGSEL(4), &ela_state.regs[CS_ELA_SIGSEL4]),
492 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_TRIGCTRL(4), 0x00000000),
493 
494 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_NEXTSTATE(4), &ela_state.regs[CS_ELA_NEXTSTATE4]),
495 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_ACTION(4), &ela_state.regs[CS_ELA_ACTION4]),
496 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_ALTNEXTSTATE(4), &ela_state.regs[CS_ELA_ALTNEXTSTATE4]),
497 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_ALTACTION(4), ELA_ACTION_TRACE),
498 
499 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_COMPCTRL(4), &ela_state.regs[CS_ELA_COMPCTRL4]),
500 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_ALTCOMPCTRL(4), 0x11111111),
501 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_COUNTCOMP(4), 0x00000000),
502 
503 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_TWBSEL(4), &ela_state.regs[CS_ELA_TWBSEL4]),
504 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_EXTMASK(4), 0x00000000),
505 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_EXTCOMP(4), 0x00000000),
506 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_QUALMASK(4), 0x00000000),
507 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_QUALCOMP(4), 0x00000000),
508 
509 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(4, 0), &ela_state.regs[CS_ELA_SIGMASK4_0]),
510 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(4, 1), &ela_state.regs[CS_ELA_SIGMASK4_1]),
511 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(4, 2), &ela_state.regs[CS_ELA_SIGMASK4_2]),
512 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(4, 3), &ela_state.regs[CS_ELA_SIGMASK4_3]),
513 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(4, 4), &ela_state.regs[CS_ELA_SIGMASK4_4]),
514 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(4, 5), &ela_state.regs[CS_ELA_SIGMASK4_5]),
515 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(4, 6), &ela_state.regs[CS_ELA_SIGMASK4_6]),
516 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGMASK(4, 7), &ela_state.regs[CS_ELA_SIGMASK4_7]),
517 
518 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(4, 0), &ela_state.regs[CS_ELA_SIGCOMP4_0]),
519 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(4, 1), &ela_state.regs[CS_ELA_SIGCOMP4_1]),
520 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(4, 2), &ela_state.regs[CS_ELA_SIGCOMP4_2]),
521 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(4, 3), &ela_state.regs[CS_ELA_SIGCOMP4_3]),
522 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(4, 4), &ela_state.regs[CS_ELA_SIGCOMP4_4]),
523 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(4, 5), &ela_state.regs[CS_ELA_SIGCOMP4_5]),
524 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(4, 6), &ela_state.regs[CS_ELA_SIGCOMP4_6]),
525 	WRITE_PTR_OP(CS_ELA_BASE_ADDR + ELA_SIGCOMP(4, 7), &ela_state.regs[CS_ELA_SIGCOMP4_7]),
526 
527 	WRITE_IMM_OP(CS_GPU_COMMAND_ADDR, CS_GPU_COMMAND_TRACE_CONTROL_EN),
528 
529 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_CTRL, ELA_CTRL_RUN),
530 
531 	BIT_OR_OP(&ela_state.enabled, 0x1),
532 };
533 
534 static struct kbase_debug_coresight_csf_op ela_disable_ops[] = {
535 	WRITE_IMM_OP(CS_ELA_BASE_ADDR + ELA_CTRL, 0x00000000),
536 	/* Poll CTRL.TRACE_BUSY until it becomes low to ensure that trace has stopped. */
537 	POLL_OP(CS_ELA_BASE_ADDR + ELA_CTRL, ELA_CTRL_TRACE_BUSY, 0x0),
538 
539 	BIT_AND_OP(&ela_state.enabled, 0x0),
540 };
541 
parse_signal_groups(struct coresight_mali_source_drvdata * drvdata)542 static int parse_signal_groups(struct coresight_mali_source_drvdata *drvdata)
543 {
544 	struct device_node *signal_groups = NULL;
545 	unsigned int siggrp_idx;
546 
547 	if (drvdata->base.dev->of_node)
548 		signal_groups = of_get_child_by_name(drvdata->base.dev->of_node, "signal-groups");
549 
550 	if (!signal_groups) {
551 		dev_err(drvdata->base.dev, "Failed to find signal groups OF node");
552 		return -EINVAL;
553 	}
554 
555 	for (siggrp_idx = 0; siggrp_idx < CS_ELA_MAX_SIGNAL_GROUPS; siggrp_idx++) {
556 		char buf[CS_SG_NAME_MAX_LEN];
557 		ssize_t res;
558 		const char *name;
559 		struct property *prop;
560 
561 		res = snprintf(buf, CS_SG_NAME_MAX_LEN, "sg%d", siggrp_idx);
562 		if (res <= 0) {
563 			dev_err(drvdata->base.dev,
564 				"Signal group name %d snprintf failed unexpectedly", siggrp_idx);
565 			return -EINVAL;
566 		}
567 
568 		of_property_for_each_string(signal_groups, buf, prop, name) {
569 			int sig_type;
570 
571 			for (sig_type = 0; sig_type < CS_ELA_NR_SIGTYPE; sig_type++) {
572 				if (!strncmp(signal_type_names[sig_type], name,
573 					     strlen(signal_type_names[sig_type]))) {
574 					ela_state.signal_types[sig_type] = (1U << siggrp_idx);
575 					ela_state.supported_tracemodes |=
576 						(1U << signal_type_tracemode_map[sig_type]);
577 				}
578 			}
579 		}
580 	}
581 
582 	/* Add TRACEMODE_NONE as supported to allow printing */
583 	ela_state.supported_tracemodes |= (1U << CS_ELA_TRACEMODE_NONE);
584 
585 	return 0;
586 }
587 
coresight_mali_sources_init_drvdata(struct coresight_mali_source_drvdata * drvdata)588 int coresight_mali_sources_init_drvdata(struct coresight_mali_source_drvdata *drvdata)
589 {
590 	int res = 0;
591 
592 #if KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE
593 	drvdata->type_name = type_name;
594 #endif
595 
596 	drvdata->base.kbase_client = kbase_debug_coresight_csf_register(
597 		drvdata->base.gpu_dev, ela_range, NELEMS(ela_range));
598 	if (drvdata->base.kbase_client == NULL) {
599 		dev_err(drvdata->base.dev, "Registration with full range failed unexpectedly");
600 		return -EINVAL;
601 	}
602 
603 	drvdata->trcid = CS_MALI_TRACE_ID;
604 
605 	drvdata->base.enable_seq.ops = ela_enable_ops;
606 	drvdata->base.enable_seq.nr_ops = NELEMS(ela_enable_ops);
607 
608 	drvdata->base.disable_seq.ops = ela_disable_ops;
609 	drvdata->base.disable_seq.nr_ops = NELEMS(ela_disable_ops);
610 
611 	drvdata->base.config = kbase_debug_coresight_csf_config_create(
612 		drvdata->base.kbase_client, &drvdata->base.enable_seq, &drvdata->base.disable_seq);
613 	if (!drvdata->base.config) {
614 		dev_err(drvdata->base.dev, "config create failed unexpectedly");
615 		return -EINVAL;
616 	}
617 
618 	res = parse_signal_groups(drvdata);
619 	if (res) {
620 		dev_err(drvdata->base.dev, "Failed to parse signal groups");
621 		return res;
622 	}
623 
624 	return 0;
625 }
626 
coresight_mali_sources_deinit_drvdata(struct coresight_mali_source_drvdata * drvdata)627 void coresight_mali_sources_deinit_drvdata(struct coresight_mali_source_drvdata *drvdata)
628 {
629 	if (drvdata->base.config != NULL)
630 		kbase_debug_coresight_csf_config_free(drvdata->base.config);
631 
632 	if (drvdata->base.kbase_client != NULL)
633 		kbase_debug_coresight_csf_unregister(drvdata->base.kbase_client);
634 }
635 
636 static const struct of_device_id mali_source_ids[] = { { .compatible =
637 								 "arm,coresight-mali-source-ela" },
638 						       {} };
639 
640 static struct platform_driver mali_sources_platform_driver = {
641 	.probe      = coresight_mali_sources_probe,
642 	.remove     = coresight_mali_sources_remove,
643 	.driver = {
644 		.name = "coresight-mali-source-ela",
645 		.owner = THIS_MODULE,
646 		.of_match_table = mali_source_ids,
647 		.suppress_bind_attrs    = true,
648 	},
649 };
650 
mali_sources_init(void)651 static int __init mali_sources_init(void)
652 {
653 	return platform_driver_register(&mali_sources_platform_driver);
654 }
655 
mali_sources_exit(void)656 static void __exit mali_sources_exit(void)
657 {
658 	platform_driver_unregister(&mali_sources_platform_driver);
659 }
660 
661 module_init(mali_sources_init);
662 module_exit(mali_sources_exit);
663 
664 MODULE_AUTHOR("Arm Ltd.");
665 MODULE_DESCRIPTION("Arm Coresight Mali source ELA");
666 MODULE_LICENSE("GPL");
667