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", ®s[0], ®s[1], ®s[2], ®s[3],
368 ®s[4], ®s[5], ®s[6], ®s[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