import OT_8063_20170412 mali driver
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / mt8127 / mali / mali / linux / mali_kernel_sysfs.c
CommitLineData
6fa3eb70
S
1/**
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
db9a41fa 4 * (C) COPYRIGHT 2011-2015 ARM Limited
6fa3eb70
S
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10
11
12/**
13 * @file mali_kernel_sysfs.c
14 * Implementation of some sysfs data exports
15 */
16
17#include <linux/kernel.h>
18#include <linux/fs.h>
19#include <linux/device.h>
20#include <linux/module.h>
21#include "mali_kernel_license.h"
22#include "mali_kernel_common.h"
23#include "mali_ukk.h"
24
25#if MALI_LICENSE_IS_GPL
26
27#include <linux/seq_file.h>
28#include <linux/debugfs.h>
29#include <asm/uaccess.h>
30#include <linux/module.h>
31#include <linux/mali/mali_utgard.h>
6fa3eb70
S
32#include "mali_kernel_sysfs.h"
33#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
34#include <linux/slab.h>
35#include "mali_osk_profiling.h"
36#endif
37
38#include <linux/mali/mali_utgard.h>
39#include "mali_pm.h"
40#include "mali_pmu.h"
41#include "mali_group.h"
42#include "mali_gp.h"
43#include "mali_pp.h"
44#include "mali_l2_cache.h"
45#include "mali_hw_core.h"
46#include "mali_kernel_core.h"
47#include "mali_user_settings_db.h"
48#include "mali_profiling_internal.h"
49#include "mali_gp_job.h"
50#include "mali_pp_job.h"
db9a41fa 51#include "mali_executor.h"
6fa3eb70
S
52
53#define PRIVATE_DATA_COUNTER_MAKE_GP(src) (src)
54#define PRIVATE_DATA_COUNTER_MAKE_PP(src) ((1 << 24) | src)
55#define PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(src, sub_job) ((1 << 24) | (1 << 16) | (sub_job << 8) | src)
56#define PRIVATE_DATA_COUNTER_IS_PP(a) ((((a) >> 24) & 0xFF) ? MALI_TRUE : MALI_FALSE)
57#define PRIVATE_DATA_COUNTER_GET_SRC(a) (a & 0xFF)
58#define PRIVATE_DATA_COUNTER_IS_SUB_JOB(a) ((((a) >> 16) & 0xFF) ? MALI_TRUE : MALI_FALSE)
59#define PRIVATE_DATA_COUNTER_GET_SUB_JOB(a) (((a) >> 8) & 0xFF)
60
61#define POWER_BUFFER_SIZE 3
62
63static struct dentry *mali_debugfs_dir = NULL;
64
65typedef enum {
66 _MALI_DEVICE_SUSPEND,
67 _MALI_DEVICE_RESUME,
68 _MALI_DEVICE_DVFS_PAUSE,
69 _MALI_DEVICE_DVFS_RESUME,
70 _MALI_MAX_EVENTS
71} _mali_device_debug_power_events;
72
db9a41fa 73static const char *const mali_power_events[_MALI_MAX_EVENTS] = {
6fa3eb70
S
74 [_MALI_DEVICE_SUSPEND] = "suspend",
75 [_MALI_DEVICE_RESUME] = "resume",
76 [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause",
77 [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume",
78};
79
80static mali_bool power_always_on_enabled = MALI_FALSE;
81
6fa3eb70
S
82static int open_copy_private_data(struct inode *inode, struct file *filp)
83{
84 filp->private_data = inode->i_private;
85 return 0;
86}
87
88static ssize_t group_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
89{
90 int r;
91 char buffer[64];
92 struct mali_group *group;
93
94 group = (struct mali_group *)filp->private_data;
95 MALI_DEBUG_ASSERT_POINTER(group);
96
db9a41fa
S
97 r = snprintf(buffer, 64, "%u\n",
98 mali_executor_group_is_disabled(group) ? 0 : 1);
6fa3eb70
S
99
100 return simple_read_from_buffer(buf, count, offp, buffer, r);
101}
102
103static ssize_t group_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
104{
105 int r;
106 char buffer[64];
107 unsigned long val;
108 struct mali_group *group;
109
110 group = (struct mali_group *)filp->private_data;
111 MALI_DEBUG_ASSERT_POINTER(group);
112
113 if (count >= sizeof(buffer)) {
114 return -ENOMEM;
115 }
116
117 if (copy_from_user(&buffer[0], buf, count)) {
118 return -EFAULT;
119 }
120 buffer[count] = '\0';
121
db9a41fa 122 r = kstrtoul(&buffer[0], 10, &val);
6fa3eb70
S
123 if (0 != r) {
124 return -EINVAL;
125 }
126
127 switch (val) {
128 case 1:
db9a41fa 129 mali_executor_group_enable(group);
6fa3eb70
S
130 break;
131 case 0:
db9a41fa 132 mali_executor_group_disable(group);
6fa3eb70
S
133 break;
134 default:
135 return -EINVAL;
136 break;
137 }
138
139 *offp += count;
140 return count;
141}
142
143static const struct file_operations group_enabled_fops = {
144 .owner = THIS_MODULE,
145 .open = open_copy_private_data,
146 .read = group_enabled_read,
147 .write = group_enabled_write,
148};
149
150static ssize_t hw_core_base_addr_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
151{
152 int r;
153 char buffer[64];
154 struct mali_hw_core *hw_core;
155
156 hw_core = (struct mali_hw_core *)filp->private_data;
157 MALI_DEBUG_ASSERT_POINTER(hw_core);
158
db9a41fa 159 r = snprintf(buffer, 64, "0x%lX\n", hw_core->phys_addr);
6fa3eb70
S
160
161 return simple_read_from_buffer(buf, count, offp, buffer, r);
162}
163
164static const struct file_operations hw_core_base_addr_fops = {
165 .owner = THIS_MODULE,
166 .open = open_copy_private_data,
167 .read = hw_core_base_addr_read,
168};
169
170static ssize_t profiling_counter_src_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
171{
db9a41fa
S
172 u32 is_pp = PRIVATE_DATA_COUNTER_IS_PP((uintptr_t)filp->private_data);
173 u32 src_id = PRIVATE_DATA_COUNTER_GET_SRC((uintptr_t)filp->private_data);
174 mali_bool is_sub_job = PRIVATE_DATA_COUNTER_IS_SUB_JOB((uintptr_t)filp->private_data);
175 u32 sub_job = PRIVATE_DATA_COUNTER_GET_SUB_JOB((uintptr_t)filp->private_data);
6fa3eb70
S
176 char buf[64];
177 int r;
178 u32 val;
179
180 if (MALI_TRUE == is_pp) {
181 /* PP counter */
182 if (MALI_TRUE == is_sub_job) {
183 /* Get counter for a particular sub job */
184 if (0 == src_id) {
185 val = mali_pp_job_get_pp_counter_sub_job_src0(sub_job);
186 } else {
187 val = mali_pp_job_get_pp_counter_sub_job_src1(sub_job);
188 }
189 } else {
190 /* Get default counter for all PP sub jobs */
191 if (0 == src_id) {
192 val = mali_pp_job_get_pp_counter_global_src0();
193 } else {
194 val = mali_pp_job_get_pp_counter_global_src1();
195 }
196 }
197 } else {
198 /* GP counter */
199 if (0 == src_id) {
200 val = mali_gp_job_get_gp_counter_src0();
201 } else {
202 val = mali_gp_job_get_gp_counter_src1();
203 }
204 }
205
206 if (MALI_HW_CORE_NO_COUNTER == val) {
db9a41fa 207 r = snprintf(buf, 64, "-1\n");
6fa3eb70 208 } else {
db9a41fa 209 r = snprintf(buf, 64, "%u\n", val);
6fa3eb70
S
210 }
211
212 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
213}
214
215static ssize_t profiling_counter_src_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
216{
db9a41fa
S
217 u32 is_pp = PRIVATE_DATA_COUNTER_IS_PP((uintptr_t)filp->private_data);
218 u32 src_id = PRIVATE_DATA_COUNTER_GET_SRC((uintptr_t)filp->private_data);
219 mali_bool is_sub_job = PRIVATE_DATA_COUNTER_IS_SUB_JOB((uintptr_t)filp->private_data);
220 u32 sub_job = PRIVATE_DATA_COUNTER_GET_SUB_JOB((uintptr_t)filp->private_data);
6fa3eb70
S
221 char buf[64];
222 long val;
223 int ret;
224
225 if (cnt >= sizeof(buf)) {
226 return -EINVAL;
227 }
228
229 if (copy_from_user(&buf, ubuf, cnt)) {
230 return -EFAULT;
231 }
232
233 buf[cnt] = 0;
234
db9a41fa 235 ret = kstrtol(buf, 10, &val);
6fa3eb70
S
236 if (ret < 0) {
237 return ret;
238 }
239
240 if (val < 0) {
241 /* any negative input will disable counter */
242 val = MALI_HW_CORE_NO_COUNTER;
243 }
244
245 if (MALI_TRUE == is_pp) {
246 /* PP counter */
247 if (MALI_TRUE == is_sub_job) {
248 /* Set counter for a particular sub job */
249 if (0 == src_id) {
250 mali_pp_job_set_pp_counter_sub_job_src0(sub_job, (u32)val);
251 } else {
252 mali_pp_job_set_pp_counter_sub_job_src1(sub_job, (u32)val);
253 }
254 } else {
255 /* Set default counter for all PP sub jobs */
256 if (0 == src_id) {
257 mali_pp_job_set_pp_counter_global_src0((u32)val);
258 } else {
259 mali_pp_job_set_pp_counter_global_src1((u32)val);
260 }
261 }
262 } else {
263 /* GP counter */
264 if (0 == src_id) {
265 mali_gp_job_set_gp_counter_src0((u32)val);
266 } else {
267 mali_gp_job_set_gp_counter_src1((u32)val);
268 }
269 }
270
271 *ppos += cnt;
272 return cnt;
273}
274
275static const struct file_operations profiling_counter_src_fops = {
276 .owner = THIS_MODULE,
277 .open = open_copy_private_data,
278 .read = profiling_counter_src_read,
279 .write = profiling_counter_src_write,
280};
281
282static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
283{
284 char buf[64];
285 int r;
286 u32 val;
287 struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
288
289 if (0 == src_id) {
290 val = mali_l2_cache_core_get_counter_src0(l2_core);
291 } else {
292 val = mali_l2_cache_core_get_counter_src1(l2_core);
293 }
294
295 if (MALI_HW_CORE_NO_COUNTER == val) {
db9a41fa 296 r = snprintf(buf, 64, "-1\n");
6fa3eb70 297 } else {
db9a41fa 298 r = snprintf(buf, 64, "%u\n", val);
6fa3eb70
S
299 }
300 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
301}
302
303static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
304{
305 struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
306 char buf[64];
307 long val;
308 int ret;
309
310 if (cnt >= sizeof(buf)) {
311 return -EINVAL;
312 }
313
314 if (copy_from_user(&buf, ubuf, cnt)) {
315 return -EFAULT;
316 }
317
318 buf[cnt] = 0;
319
db9a41fa 320 ret = kstrtol(buf, 10, &val);
6fa3eb70
S
321 if (ret < 0) {
322 return ret;
323 }
324
325 if (val < 0) {
326 /* any negative input will disable counter */
327 val = MALI_HW_CORE_NO_COUNTER;
328 }
329
db9a41fa 330 mali_l2_cache_core_set_counter_src(l2_core, src_id, (u32)val);
6fa3eb70
S
331
332 *ppos += cnt;
333 return cnt;
334}
335
336static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
337{
338 char buf[64];
339 long val;
340 int ret;
341 u32 l2_id;
342 struct mali_l2_cache_core *l2_cache;
343
344 if (cnt >= sizeof(buf)) {
345 return -EINVAL;
346 }
347
348 if (copy_from_user(&buf, ubuf, cnt)) {
349 return -EFAULT;
350 }
351
352 buf[cnt] = 0;
353
db9a41fa 354 ret = kstrtol(buf, 10, &val);
6fa3eb70
S
355 if (ret < 0) {
356 return ret;
357 }
358
359 if (val < 0) {
360 /* any negative input will disable counter */
361 val = MALI_HW_CORE_NO_COUNTER;
362 }
363
364 l2_id = 0;
365 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
366 while (NULL != l2_cache) {
db9a41fa 367 mali_l2_cache_core_set_counter_src(l2_cache, src_id, (u32)val);
6fa3eb70
S
368
369 /* try next L2 */
370 l2_id++;
371 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
372 }
373
374 *ppos += cnt;
375 return cnt;
376}
377
378static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
379{
380 return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
381}
382
383static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
384{
385 return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
386}
387
388static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
389{
390 return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
391}
392
393static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
394{
395 return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
396}
397
398static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
399{
400 return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
401}
402
403static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
404{
405 return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
406}
407
408static const struct file_operations l2_l2x_counter_src0_fops = {
409 .owner = THIS_MODULE,
410 .open = open_copy_private_data,
411 .read = l2_l2x_counter_src0_read,
412 .write = l2_l2x_counter_src0_write,
413};
414
415static const struct file_operations l2_l2x_counter_src1_fops = {
416 .owner = THIS_MODULE,
417 .open = open_copy_private_data,
418 .read = l2_l2x_counter_src1_read,
419 .write = l2_l2x_counter_src1_write,
420};
421
422static const struct file_operations l2_all_counter_src0_fops = {
423 .owner = THIS_MODULE,
424 .write = l2_all_counter_src0_write,
425};
426
427static const struct file_operations l2_all_counter_src1_fops = {
428 .owner = THIS_MODULE,
429 .write = l2_all_counter_src1_write,
430};
431
db9a41fa
S
432static ssize_t l2_l2x_counter_valx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
433{
434 char buf[64];
435 int r;
436 u32 src0 = 0;
437 u32 val0 = 0;
438 u32 src1 = 0;
439 u32 val1 = 0;
440 u32 val = -1;
441 struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
442
443 mali_l2_cache_core_get_counter_values(l2_core, &src0, &val0, &src1, &val1);
444
445 if (0 == src_id) {
446 if (MALI_HW_CORE_NO_COUNTER != val0) {
447 val = val0;
448 }
449 } else {
450 if (MALI_HW_CORE_NO_COUNTER != val1) {
451 val = val1;
452 }
453 }
454
455 r = snprintf(buf, 64, "%u\n", val);
456
457 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
458}
459
460static ssize_t l2_l2x_counter_val0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
461{
462 return l2_l2x_counter_valx_read(filp, ubuf, cnt, ppos, 0);
463}
464
465static ssize_t l2_l2x_counter_val1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
466{
467 return l2_l2x_counter_valx_read(filp, ubuf, cnt, ppos, 1);
468}
469
470static const struct file_operations l2_l2x_counter_val0_fops = {
471 .owner = THIS_MODULE,
472 .open = open_copy_private_data,
473 .read = l2_l2x_counter_val0_read,
474};
475
476static const struct file_operations l2_l2x_counter_val1_fops = {
477 .owner = THIS_MODULE,
478 .open = open_copy_private_data,
479 .read = l2_l2x_counter_val1_read,
480};
481
6fa3eb70
S
482static ssize_t power_always_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
483{
484 unsigned long val;
485 int ret;
486 char buf[32];
487
488 cnt = min(cnt, sizeof(buf) - 1);
489 if (copy_from_user(buf, ubuf, cnt)) {
490 return -EFAULT;
491 }
492 buf[cnt] = '\0';
493
db9a41fa 494 ret = kstrtoul(buf, 10, &val);
6fa3eb70
S
495 if (0 != ret) {
496 return ret;
497 }
498
499 /* Update setting (not exactly thread safe) */
500 if (1 == val && MALI_FALSE == power_always_on_enabled) {
501 power_always_on_enabled = MALI_TRUE;
db9a41fa 502 _mali_osk_pm_dev_ref_get_sync();
6fa3eb70
S
503 } else if (0 == val && MALI_TRUE == power_always_on_enabled) {
504 power_always_on_enabled = MALI_FALSE;
db9a41fa 505 _mali_osk_pm_dev_ref_put();
6fa3eb70
S
506 }
507
508 *ppos += cnt;
509 return cnt;
510}
511
512static ssize_t power_always_on_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
513{
514 if (MALI_TRUE == power_always_on_enabled) {
515 return simple_read_from_buffer(ubuf, cnt, ppos, "1\n", 2);
516 } else {
517 return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2);
518 }
519}
520
521static const struct file_operations power_always_on_fops = {
522 .owner = THIS_MODULE,
523 .read = power_always_on_read,
524 .write = power_always_on_write,
525};
526
527static ssize_t power_power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
528{
db9a41fa
S
529 if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_SUSPEND], strlen(mali_power_events[_MALI_DEVICE_SUSPEND]) - 1)) {
530 mali_pm_os_suspend(MALI_TRUE);
531 } else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_RESUME], strlen(mali_power_events[_MALI_DEVICE_RESUME]) - 1)) {
6fa3eb70 532 mali_pm_os_resume();
db9a41fa 533 } else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_DVFS_PAUSE], strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE]) - 1)) {
6fa3eb70 534 mali_dev_pause();
db9a41fa 535 } else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_DVFS_RESUME], strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME]) - 1)) {
6fa3eb70
S
536 mali_dev_resume();
537 }
538 *ppos += cnt;
539 return cnt;
540}
541
542static loff_t power_power_events_seek(struct file *file, loff_t offset, int orig)
543{
544 file->f_pos = offset;
545 return 0;
546}
547
548static const struct file_operations power_power_events_fops = {
549 .owner = THIS_MODULE,
550 .write = power_power_events_write,
551 .llseek = power_power_events_seek,
552};
553
554#if MALI_STATE_TRACKING
555static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
556{
557 u32 len = 0;
558 u32 size;
559 char *buf;
560
561 size = seq_get_buf(seq_file, &buf);
562
db9a41fa 563 if (!size) {
6fa3eb70
S
564 return -ENOMEM;
565 }
566
567 /* Create the internal state dump. */
db9a41fa
S
568 len = snprintf(buf + len, size - len, "Mali device driver %s\n", SVN_REV_STRING);
569 len += snprintf(buf + len, size - len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE);
6fa3eb70
S
570
571 len += _mali_kernel_core_dump_state(buf + len, size - len);
572
573 seq_commit(seq_file, len);
574
575 return 0;
576}
577
578static int mali_seq_internal_state_open(struct inode *inode, struct file *file)
579{
580 return single_open(file, mali_seq_internal_state_show, NULL);
581}
582
583static const struct file_operations mali_seq_internal_state_fops = {
584 .owner = THIS_MODULE,
585 .open = mali_seq_internal_state_open,
586 .read = seq_read,
587 .llseek = seq_lseek,
588 .release = single_release,
589};
590#endif /* MALI_STATE_TRACKING */
591
592#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
593static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
594{
595 char buf[64];
596 int r;
597
db9a41fa 598 r = snprintf(buf, 64, "%u\n", _mali_internal_profiling_is_recording() ? 1 : 0);
6fa3eb70
S
599 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
600}
601
602static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
603{
604 char buf[64];
605 unsigned long val;
606 int ret;
607
608 if (cnt >= sizeof(buf)) {
609 return -EINVAL;
610 }
611
612 if (copy_from_user(&buf, ubuf, cnt)) {
613 return -EFAULT;
614 }
615
616 buf[cnt] = 0;
617
db9a41fa 618 ret = kstrtoul(buf, 10, &val);
6fa3eb70
S
619 if (ret < 0) {
620 return ret;
621 }
622
623 if (val != 0) {
624 u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */
625
626 /* check if we are already recording */
627 if (MALI_TRUE == _mali_internal_profiling_is_recording()) {
628 MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n"));
629 return -EFAULT;
630 }
631
632 /* check if we need to clear out an old recording first */
633 if (MALI_TRUE == _mali_internal_profiling_have_recording()) {
634 if (_MALI_OSK_ERR_OK != _mali_internal_profiling_clear()) {
635 MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n"));
636 return -EFAULT;
637 }
638 }
639
640 /* start recording profiling data */
641 if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) {
642 MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n"));
643 return -EFAULT;
644 }
645
646 MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit));
647 } else {
648 /* stop recording profiling data */
649 u32 count = 0;
650 if (_MALI_OSK_ERR_OK != _mali_internal_profiling_stop(&count)) {
651 MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n"));
652 return -EFAULT;
653 }
654
655 MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count));
656 }
657
658 *ppos += cnt;
659 return cnt;
660}
661
662static const struct file_operations profiling_record_fops = {
663 .owner = THIS_MODULE,
664 .read = profiling_record_read,
665 .write = profiling_record_write,
666};
667
668static void *profiling_events_start(struct seq_file *s, loff_t *pos)
669{
670 loff_t *spos;
671
672 /* check if we have data avaiable */
673 if (MALI_TRUE != _mali_internal_profiling_have_recording()) {
674 return NULL;
675 }
676
677 spos = kmalloc(sizeof(loff_t), GFP_KERNEL);
678 if (NULL == spos) {
679 return NULL;
680 }
681
682 *spos = *pos;
683 return spos;
684}
685
686static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos)
687{
688 loff_t *spos = v;
689
690 /* check if we have data avaiable */
691 if (MALI_TRUE != _mali_internal_profiling_have_recording()) {
692 return NULL;
693 }
694
695 /* check if the next entry actually is avaiable */
696 if (_mali_internal_profiling_get_count() <= (u32)(*spos + 1)) {
697 return NULL;
698 }
699
700 *pos = ++*spos;
701 return spos;
702}
703
704static void profiling_events_stop(struct seq_file *s, void *v)
705{
706 kfree(v);
707}
708
709static int profiling_events_show(struct seq_file *seq_file, void *v)
710{
711 loff_t *spos = v;
712 u32 index;
713 u64 timestamp;
714 u32 event_id;
715 u32 data[5];
716
db9a41fa 717 index = (u32) * spos;
6fa3eb70
S
718
719 /* Retrieve all events */
720 if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, &timestamp, &event_id, data)) {
721 seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
722 return 0;
723 }
724
725 return 0;
726}
727
728static int profiling_events_show_human_readable(struct seq_file *seq_file, void *v)
729{
730#define MALI_EVENT_ID_IS_HW(event_id) (((event_id & 0x00FF0000) >= MALI_PROFILING_EVENT_CHANNEL_GP0) && ((event_id & 0x00FF0000) <= MALI_PROFILING_EVENT_CHANNEL_PP7))
731
732 static u64 start_time = 0;
733 loff_t *spos = v;
734 u32 index;
735 u64 timestamp;
736 u32 event_id;
737 u32 data[5];
738
db9a41fa 739 index = (u32) * spos;
6fa3eb70
S
740
741 /* Retrieve all events */
742 if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, &timestamp, &event_id, data)) {
743 seq_printf(seq_file, "%llu %u %u %u %u %u %u # ", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
744
745 if (0 == index) {
746 start_time = timestamp;
747 }
748
749 seq_printf(seq_file, "[%06u] ", index);
750
db9a41fa 751 switch (event_id & 0x0F000000) {
6fa3eb70
S
752 case MALI_PROFILING_EVENT_TYPE_SINGLE:
753 seq_printf(seq_file, "SINGLE | ");
754 break;
755 case MALI_PROFILING_EVENT_TYPE_START:
756 seq_printf(seq_file, "START | ");
757 break;
758 case MALI_PROFILING_EVENT_TYPE_STOP:
759 seq_printf(seq_file, "STOP | ");
760 break;
761 case MALI_PROFILING_EVENT_TYPE_SUSPEND:
762 seq_printf(seq_file, "SUSPEND | ");
763 break;
764 case MALI_PROFILING_EVENT_TYPE_RESUME:
765 seq_printf(seq_file, "RESUME | ");
766 break;
767 default:
768 seq_printf(seq_file, "0x%01X | ", (event_id & 0x0F000000) >> 24);
769 break;
770 }
771
db9a41fa 772 switch (event_id & 0x00FF0000) {
6fa3eb70
S
773 case MALI_PROFILING_EVENT_CHANNEL_SOFTWARE:
774 seq_printf(seq_file, "SW | ");
775 break;
776 case MALI_PROFILING_EVENT_CHANNEL_GP0:
777 seq_printf(seq_file, "GP0 | ");
778 break;
779 case MALI_PROFILING_EVENT_CHANNEL_PP0:
780 seq_printf(seq_file, "PP0 | ");
781 break;
782 case MALI_PROFILING_EVENT_CHANNEL_PP1:
783 seq_printf(seq_file, "PP1 | ");
784 break;
785 case MALI_PROFILING_EVENT_CHANNEL_PP2:
786 seq_printf(seq_file, "PP2 | ");
787 break;
788 case MALI_PROFILING_EVENT_CHANNEL_PP3:
789 seq_printf(seq_file, "PP3 | ");
790 break;
791 case MALI_PROFILING_EVENT_CHANNEL_PP4:
792 seq_printf(seq_file, "PP4 | ");
793 break;
794 case MALI_PROFILING_EVENT_CHANNEL_PP5:
795 seq_printf(seq_file, "PP5 | ");
796 break;
797 case MALI_PROFILING_EVENT_CHANNEL_PP6:
798 seq_printf(seq_file, "PP6 | ");
799 break;
800 case MALI_PROFILING_EVENT_CHANNEL_PP7:
801 seq_printf(seq_file, "PP7 | ");
802 break;
803 case MALI_PROFILING_EVENT_CHANNEL_GPU:
804 seq_printf(seq_file, "GPU | ");
805 break;
806 default:
807 seq_printf(seq_file, "0x%02X | ", (event_id & 0x00FF0000) >> 16);
808 break;
809 }
810
811 if (MALI_EVENT_ID_IS_HW(event_id)) {
812 if (((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_START) || ((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_STOP)) {
db9a41fa 813 switch (event_id & 0x0000FFFF) {
6fa3eb70
S
814 case MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL:
815 seq_printf(seq_file, "PHYSICAL | ");
816 break;
817 case MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL:
818 seq_printf(seq_file, "VIRTUAL | ");
819 break;
820 default:
821 seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
822 break;
823 }
824 } else {
825 seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
826 }
827 } else {
828 seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
829 }
830
831 seq_printf(seq_file, "T0 + 0x%016llX\n", timestamp - start_time);
832
833 return 0;
834 }
835
836 return 0;
837}
838
839static const struct seq_operations profiling_events_seq_ops = {
840 .start = profiling_events_start,
841 .next = profiling_events_next,
842 .stop = profiling_events_stop,
843 .show = profiling_events_show
844};
845
846static int profiling_events_open(struct inode *inode, struct file *file)
847{
848 return seq_open(file, &profiling_events_seq_ops);
849}
850
851static const struct file_operations profiling_events_fops = {
852 .owner = THIS_MODULE,
853 .open = profiling_events_open,
854 .read = seq_read,
855 .llseek = seq_lseek,
856 .release = seq_release,
857};
858
859static const struct seq_operations profiling_events_human_readable_seq_ops = {
860 .start = profiling_events_start,
861 .next = profiling_events_next,
862 .stop = profiling_events_stop,
863 .show = profiling_events_show_human_readable
864};
865
866static int profiling_events_human_readable_open(struct inode *inode, struct file *file)
867{
868 return seq_open(file, &profiling_events_human_readable_seq_ops);
869}
870
871static const struct file_operations profiling_events_human_readable_fops = {
872 .owner = THIS_MODULE,
873 .open = profiling_events_human_readable_open,
874 .read = seq_read,
875 .llseek = seq_lseek,
876 .release = seq_release,
877};
878
879#endif
880
db9a41fa 881static int memory_debugfs_show(struct seq_file *s, void *private_data)
6fa3eb70 882{
db9a41fa
S
883 seq_printf(s, " %-25s %-10s %-10s %-15s %-15s %-10s %-10s\n"\
884 "==============================================================================================================\n",
885 "Name (:bytes)", "pid", "mali_mem", "max_mali_mem",
886 "external_mem", "ump_mem", "dma_mem");
887 mali_session_memory_tracking(s);
888 return 0;
889}
6fa3eb70 890
db9a41fa
S
891static int memory_debugfs_open(struct inode *inode, struct file *file)
892{
893 return single_open(file, memory_debugfs_show, inode->i_private);
6fa3eb70
S
894}
895
896static const struct file_operations memory_usage_fops = {
897 .owner = THIS_MODULE,
db9a41fa
S
898 .open = memory_debugfs_open,
899 .read = seq_read,
900 .llseek = seq_lseek,
901 .release = single_release,
6fa3eb70
S
902};
903
904static ssize_t utilization_gp_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
905{
906 char buf[64];
907 size_t r;
db9a41fa 908 u32 uval = _mali_ukk_utilization_gp_pp();
6fa3eb70
S
909
910 r = snprintf(buf, 64, "%u\n", uval);
911 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
912}
913
914static ssize_t utilization_gp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
915{
916 char buf[64];
917 size_t r;
db9a41fa 918 u32 uval = _mali_ukk_utilization_gp();
6fa3eb70
S
919
920 r = snprintf(buf, 64, "%u\n", uval);
921 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
922}
923
924static ssize_t utilization_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
925{
926 char buf[64];
927 size_t r;
db9a41fa 928 u32 uval = _mali_ukk_utilization_pp();
6fa3eb70
S
929
930 r = snprintf(buf, 64, "%u\n", uval);
931 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
932}
933
934
935static const struct file_operations utilization_gp_pp_fops = {
936 .owner = THIS_MODULE,
937 .read = utilization_gp_pp_read,
938};
939
940static const struct file_operations utilization_gp_fops = {
941 .owner = THIS_MODULE,
942 .read = utilization_gp_read,
943};
944
945static const struct file_operations utilization_pp_fops = {
946 .owner = THIS_MODULE,
947 .read = utilization_pp_read,
948};
949
950static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
951{
952 unsigned long val;
953 int ret;
954 _mali_uk_user_setting_t setting;
955 char buf[32];
956
957 cnt = min(cnt, sizeof(buf) - 1);
958 if (copy_from_user(buf, ubuf, cnt)) {
959 return -EFAULT;
960 }
961 buf[cnt] = '\0';
962
db9a41fa 963 ret = kstrtoul(buf, 10, &val);
6fa3eb70
S
964 if (0 != ret) {
965 return ret;
966 }
967
968 /* Update setting */
969 setting = (_mali_uk_user_setting_t)(filp->private_data);
970 mali_set_user_setting(setting, val);
971
972 *ppos += cnt;
973 return cnt;
974}
975
976static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
977{
978 char buf[64];
979 size_t r;
980 u32 value;
981 _mali_uk_user_setting_t setting;
982
983 setting = (_mali_uk_user_setting_t)(filp->private_data);
984 value = mali_get_user_setting(setting);
985
986 r = snprintf(buf, 64, "%u\n", value);
987 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
988}
989
990static const struct file_operations user_settings_fops = {
991 .owner = THIS_MODULE,
992 .open = open_copy_private_data,
993 .read = user_settings_read,
994 .write = user_settings_write,
995};
996
997static int mali_sysfs_user_settings_register(void)
998{
999 struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir);
1000
1001 if (mali_user_settings_dir != NULL) {
db9a41fa 1002 long i;
6fa3eb70 1003 for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++) {
db9a41fa
S
1004 debugfs_create_file(_mali_uk_user_setting_descriptions[i],
1005 0600, mali_user_settings_dir, (void *)i,
1006 &user_settings_fops);
6fa3eb70
S
1007 }
1008 }
1009
1010 return 0;
1011}
1012
6fa3eb70
S
1013static ssize_t pp_num_cores_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
1014{
1015 int ret;
1016 char buffer[32];
1017 unsigned long val;
1018
1019 if (count >= sizeof(buffer)) {
1020 return -ENOMEM;
1021 }
1022
1023 if (copy_from_user(&buffer[0], buf, count)) {
1024 return -EFAULT;
1025 }
1026 buffer[count] = '\0';
1027
db9a41fa 1028 ret = kstrtoul(&buffer[0], 10, &val);
6fa3eb70
S
1029 if (0 != ret) {
1030 return -EINVAL;
1031 }
1032
db9a41fa 1033 ret = mali_executor_set_perf_level(val, MALI_TRUE); /* override even if core scaling is disabled */
6fa3eb70
S
1034 if (ret) {
1035 return ret;
1036 }
1037
1038 *offp += count;
1039 return count;
1040}
1041
1042static ssize_t pp_num_cores_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1043{
1044 int r;
1045 char buffer[64];
1046
db9a41fa 1047 r = snprintf(buffer, 64, "%u\n", mali_executor_get_num_cores_enabled());
6fa3eb70
S
1048
1049 return simple_read_from_buffer(buf, count, offp, buffer, r);
1050}
1051
1052static const struct file_operations pp_num_cores_enabled_fops = {
1053 .owner = THIS_MODULE,
1054 .write = pp_num_cores_enabled_write,
1055 .read = pp_num_cores_enabled_read,
1056 .llseek = default_llseek,
1057};
1058
1059static ssize_t pp_num_cores_total_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1060{
1061 int r;
1062 char buffer[64];
1063
db9a41fa 1064 r = snprintf(buffer, 64, "%u\n", mali_executor_get_num_cores_total());
6fa3eb70
S
1065
1066 return simple_read_from_buffer(buf, count, offp, buffer, r);
1067}
1068
1069static const struct file_operations pp_num_cores_total_fops = {
1070 .owner = THIS_MODULE,
1071 .read = pp_num_cores_total_read,
1072};
1073
1074static ssize_t pp_core_scaling_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
1075{
1076 int ret;
1077 char buffer[32];
1078 unsigned long val;
1079
1080 if (count >= sizeof(buffer)) {
1081 return -ENOMEM;
1082 }
1083
1084 if (copy_from_user(&buffer[0], buf, count)) {
1085 return -EFAULT;
1086 }
1087 buffer[count] = '\0';
1088
db9a41fa 1089 ret = kstrtoul(&buffer[0], 10, &val);
6fa3eb70
S
1090 if (0 != ret) {
1091 return -EINVAL;
1092 }
1093
1094 switch (val) {
1095 case 1:
db9a41fa 1096 mali_executor_core_scaling_enable();
6fa3eb70
S
1097 break;
1098 case 0:
db9a41fa 1099 mali_executor_core_scaling_disable();
6fa3eb70
S
1100 break;
1101 default:
1102 return -EINVAL;
1103 break;
1104 }
1105
1106 *offp += count;
1107 return count;
1108}
1109
1110static ssize_t pp_core_scaling_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1111{
db9a41fa 1112 return simple_read_from_buffer(buf, count, offp, mali_executor_core_scaling_is_enabled() ? "1\n" : "0\n", 2);
6fa3eb70
S
1113}
1114static const struct file_operations pp_core_scaling_enabled_fops = {
1115 .owner = THIS_MODULE,
1116 .write = pp_core_scaling_enabled_write,
1117 .read = pp_core_scaling_enabled_read,
1118 .llseek = default_llseek,
1119};
1120
1121static ssize_t version_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1122{
1123 int r = 0;
1124 char buffer[64];
1125
1126 switch (mali_kernel_core_get_product_id()) {
1127 case _MALI_PRODUCT_ID_MALI200:
db9a41fa 1128 r = snprintf(buffer, 64, "Mali-200\n");
6fa3eb70
S
1129 break;
1130 case _MALI_PRODUCT_ID_MALI300:
db9a41fa 1131 r = snprintf(buffer, 64, "Mali-300\n");
6fa3eb70
S
1132 break;
1133 case _MALI_PRODUCT_ID_MALI400:
db9a41fa 1134 r = snprintf(buffer, 64, "Mali-400 MP\n");
6fa3eb70
S
1135 break;
1136 case _MALI_PRODUCT_ID_MALI450:
db9a41fa
S
1137 r = snprintf(buffer, 64, "Mali-450 MP\n");
1138 break;
1139 case _MALI_PRODUCT_ID_MALI470:
1140 r = snprintf(buffer, 64, "Mali-470 MP\n");
6fa3eb70
S
1141 break;
1142 case _MALI_PRODUCT_ID_UNKNOWN:
1143 return -EINVAL;
1144 break;
1145 };
1146
1147 return simple_read_from_buffer(buf, count, offp, buffer, r);
1148}
1149
1150static const struct file_operations version_fops = {
1151 .owner = THIS_MODULE,
1152 .read = version_read,
1153};
1154
db9a41fa
S
1155#if defined(DEBUG)
1156static int timeline_debugfs_show(struct seq_file *s, void *private_data)
1157{
1158 struct mali_session_data *session, *tmp;
1159 u32 session_seq = 1;
1160
1161 seq_printf(s, "timeline system info: \n=================\n\n");
1162
1163 mali_session_lock();
1164 MALI_SESSION_FOREACH(session, tmp, link) {
1165 seq_printf(s, "session %d <%p> start:\n", session_seq, session);
1166 mali_timeline_debug_print_system(session->timeline_system, s);
1167 seq_printf(s, "session %d end\n\n\n", session_seq++);
1168 }
1169 mali_session_unlock();
1170
1171 return 0;
1172}
1173
1174static int timeline_debugfs_open(struct inode *inode, struct file *file)
1175{
1176 return single_open(file, timeline_debugfs_show, inode->i_private);
1177}
1178
1179static const struct file_operations timeline_dump_fops = {
1180 .owner = THIS_MODULE,
1181 .open = timeline_debugfs_open,
1182 .read = seq_read,
1183 .llseek = seq_lseek,
1184 .release = single_release
1185};
1186#endif
1187
6fa3eb70
S
1188int mali_sysfs_register(const char *mali_dev_name)
1189{
1190 mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
db9a41fa 1191 if (ERR_PTR(-ENODEV) == mali_debugfs_dir) {
6fa3eb70
S
1192 /* Debugfs not supported. */
1193 mali_debugfs_dir = NULL;
1194 } else {
db9a41fa 1195 if (NULL != mali_debugfs_dir) {
6fa3eb70 1196 /* Debugfs directory created successfully; create files now */
6fa3eb70
S
1197 struct dentry *mali_power_dir;
1198 struct dentry *mali_gp_dir;
1199 struct dentry *mali_pp_dir;
1200 struct dentry *mali_l2_dir;
1201 struct dentry *mali_profiling_dir;
1202
1203 debugfs_create_file("version", 0400, mali_debugfs_dir, NULL, &version_fops);
1204
6fa3eb70
S
1205 mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
1206 if (mali_power_dir != NULL) {
1207 debugfs_create_file("always_on", 0600, mali_power_dir, NULL, &power_always_on_fops);
1208 debugfs_create_file("power_events", 0200, mali_power_dir, NULL, &power_power_events_fops);
1209 }
1210
1211 mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
1212 if (mali_gp_dir != NULL) {
1213 u32 num_groups;
db9a41fa 1214 long i;
6fa3eb70
S
1215
1216 num_groups = mali_group_get_glob_num_groups();
1217 for (i = 0; i < num_groups; i++) {
1218 struct mali_group *group = mali_group_get_glob_group(i);
1219
1220 struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
1221 if (NULL != gp_core) {
1222 struct dentry *mali_gp_gpx_dir;
1223 mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
1224 if (NULL != mali_gp_gpx_dir) {
1225 debugfs_create_file("base_addr", 0400, mali_gp_gpx_dir, &gp_core->hw_core, &hw_core_base_addr_fops);
1226 debugfs_create_file("enabled", 0600, mali_gp_gpx_dir, group, &group_enabled_fops);
1227 }
1228 break; /* no need to look for any other GP cores */
1229 }
1230
1231 }
1232 }
1233
1234 mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir);
1235 if (mali_pp_dir != NULL) {
1236 u32 num_groups;
db9a41fa 1237 long i;
6fa3eb70
S
1238
1239 debugfs_create_file("num_cores_total", 0400, mali_pp_dir, NULL, &pp_num_cores_total_fops);
1240 debugfs_create_file("num_cores_enabled", 0600, mali_pp_dir, NULL, &pp_num_cores_enabled_fops);
1241 debugfs_create_file("core_scaling_enabled", 0600, mali_pp_dir, NULL, &pp_core_scaling_enabled_fops);
1242
1243 num_groups = mali_group_get_glob_num_groups();
1244 for (i = 0; i < num_groups; i++) {
1245 struct mali_group *group = mali_group_get_glob_group(i);
1246
1247 struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
1248 if (NULL != pp_core) {
1249 char buf[16];
1250 struct dentry *mali_pp_ppx_dir;
1251 _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
1252 mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
1253 if (NULL != mali_pp_ppx_dir) {
1254 debugfs_create_file("base_addr", 0400, mali_pp_ppx_dir, &pp_core->hw_core, &hw_core_base_addr_fops);
1255 if (!mali_group_is_virtual(group)) {
1256 debugfs_create_file("enabled", 0600, mali_pp_ppx_dir, group, &group_enabled_fops);
1257 }
1258 }
1259 }
1260 }
1261 }
1262
1263 mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir);
1264 if (mali_l2_dir != NULL) {
1265 struct dentry *mali_l2_all_dir;
1266 u32 l2_id;
1267 struct mali_l2_cache_core *l2_cache;
1268
1269 mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir);
1270 if (mali_l2_all_dir != NULL) {
1271 debugfs_create_file("counter_src0", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops);
1272 debugfs_create_file("counter_src1", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops);
1273 }
1274
1275 l2_id = 0;
1276 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1277 while (NULL != l2_cache) {
1278 char buf[16];
1279 struct dentry *mali_l2_l2x_dir;
1280 _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id);
1281 mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir);
1282 if (NULL != mali_l2_l2x_dir) {
1283 debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops);
1284 debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops);
db9a41fa
S
1285 debugfs_create_file("counter_val0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_val0_fops);
1286 debugfs_create_file("counter_val1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_val1_fops);
6fa3eb70
S
1287 debugfs_create_file("base_addr", 0400, mali_l2_l2x_dir, &l2_cache->hw_core, &hw_core_base_addr_fops);
1288 }
1289
1290 /* try next L2 */
1291 l2_id++;
1292 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1293 }
1294 }
1295
db9a41fa 1296 debugfs_create_file("gpu_memory", 0444, mali_debugfs_dir, NULL, &memory_usage_fops);
6fa3eb70
S
1297
1298 debugfs_create_file("utilization_gp_pp", 0400, mali_debugfs_dir, NULL, &utilization_gp_pp_fops);
1299 debugfs_create_file("utilization_gp", 0400, mali_debugfs_dir, NULL, &utilization_gp_fops);
1300 debugfs_create_file("utilization_pp", 0400, mali_debugfs_dir, NULL, &utilization_pp_fops);
1301
1302 mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
1303 if (mali_profiling_dir != NULL) {
1304 u32 max_sub_jobs;
db9a41fa 1305 long i;
6fa3eb70
S
1306 struct dentry *mali_profiling_gp_dir;
1307 struct dentry *mali_profiling_pp_dir;
1308#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1309 struct dentry *mali_profiling_proc_dir;
1310#endif
1311 /*
1312 * Create directory where we can set GP HW counters.
1313 */
1314 mali_profiling_gp_dir = debugfs_create_dir("gp", mali_profiling_dir);
1315 if (mali_profiling_gp_dir != NULL) {
db9a41fa
S
1316 debugfs_create_file("counter_src0", 0600, mali_profiling_gp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_GP(0), &profiling_counter_src_fops);
1317 debugfs_create_file("counter_src1", 0600, mali_profiling_gp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_GP(1), &profiling_counter_src_fops);
6fa3eb70
S
1318 }
1319
1320 /*
1321 * Create directory where we can set PP HW counters.
1322 * Possible override with specific HW counters for a particular sub job
1323 * (Disable core scaling before using the override!)
1324 */
1325 mali_profiling_pp_dir = debugfs_create_dir("pp", mali_profiling_dir);
1326 if (mali_profiling_pp_dir != NULL) {
db9a41fa
S
1327 debugfs_create_file("counter_src0", 0600, mali_profiling_pp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_PP(0), &profiling_counter_src_fops);
1328 debugfs_create_file("counter_src1", 0600, mali_profiling_pp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_PP(1), &profiling_counter_src_fops);
6fa3eb70
S
1329 }
1330
db9a41fa 1331 max_sub_jobs = mali_executor_get_num_cores_total();
6fa3eb70
S
1332 for (i = 0; i < max_sub_jobs; i++) {
1333 char buf[16];
1334 struct dentry *mali_profiling_pp_x_dir;
1335 _mali_osk_snprintf(buf, sizeof(buf), "%u", i);
1336 mali_profiling_pp_x_dir = debugfs_create_dir(buf, mali_profiling_pp_dir);
1337 if (NULL != mali_profiling_pp_x_dir) {
db9a41fa
S
1338 debugfs_create_file("counter_src0",
1339 0600, mali_profiling_pp_x_dir,
1340 (void *)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(0, i),
1341 &profiling_counter_src_fops);
1342 debugfs_create_file("counter_src1",
1343 0600, mali_profiling_pp_x_dir,
1344 (void *)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(1, i),
1345 &profiling_counter_src_fops);
6fa3eb70
S
1346 }
1347 }
1348
1349#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1350 mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir);
1351 if (mali_profiling_proc_dir != NULL) {
1352 struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir);
1353 if (mali_profiling_proc_default_dir != NULL) {
db9a41fa 1354 debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void *)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops);
6fa3eb70
S
1355 }
1356 }
1357 debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
1358 debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops);
1359 debugfs_create_file("events_human_readable", 0400, mali_profiling_dir, NULL, &profiling_events_human_readable_fops);
1360#endif
1361 }
1362
1363#if MALI_STATE_TRACKING
1364 debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
1365#endif
1366
db9a41fa
S
1367#if defined(DEBUG)
1368 debugfs_create_file("timeline_dump", 0400, mali_debugfs_dir, NULL, &timeline_dump_fops);
1369#endif
6fa3eb70
S
1370 if (mali_sysfs_user_settings_register()) {
1371 /* Failed to create the debugfs entries for the user settings DB. */
1372 MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n"));
1373 }
1374 }
1375 }
1376
1377 /* Success! */
1378 return 0;
1379}
1380
1381int mali_sysfs_unregister(void)
1382{
db9a41fa 1383 if (NULL != mali_debugfs_dir) {
6fa3eb70
S
1384 debugfs_remove_recursive(mali_debugfs_dir);
1385 }
1386 return 0;
1387}
1388
1389#else /* MALI_LICENSE_IS_GPL */
1390
1391/* Dummy implementations for non-GPL */
1392
1393int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
1394{
1395 return 0;
1396}
1397
1398int mali_sysfs_unregister(void)
1399{
1400 return 0;
1401}
1402
1403#endif /* MALI_LICENSE_IS_GPL */