UPSTREAM: DT/arm,gic-v3: Documment PPI partition support
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / linux / mali_kernel_sysfs.c
1 /**
2  * Copyright (C) 2011-2014 ARM Limited. All rights reserved.
3  * 
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  * 
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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>
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"
51 #include "mali_executor.h"
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
63 static struct dentry *mali_debugfs_dir = NULL;
64
65 typedef 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
73 static const char *const mali_power_events[_MALI_MAX_EVENTS] = {
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
80 static mali_bool power_always_on_enabled = MALI_FALSE;
81
82 static int open_copy_private_data(struct inode *inode, struct file *filp)
83 {
84         filp->private_data = inode->i_private;
85         return 0;
86 }
87
88 static 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
97         r = snprintf(buffer, 64, "%u\n",
98                      mali_executor_group_is_disabled(group) ? 0 : 1);
99
100         return simple_read_from_buffer(buf, count, offp, buffer, r);
101 }
102
103 static 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
122         r = kstrtoul(&buffer[0], 10, &val);
123         if (0 != r) {
124                 return -EINVAL;
125         }
126
127         switch (val) {
128         case 1:
129                 mali_executor_group_enable(group);
130                 break;
131         case 0:
132                 mali_executor_group_disable(group);
133                 break;
134         default:
135                 return -EINVAL;
136                 break;
137         }
138
139         *offp += count;
140         return count;
141 }
142
143 static 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
150 static 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
159         r = snprintf(buffer, 64, "0x%lX\n", hw_core->phys_addr);
160
161         return simple_read_from_buffer(buf, count, offp, buffer, r);
162 }
163
164 static 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
170 static ssize_t profiling_counter_src_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
171 {
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);
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) {
207                 r = snprintf(buf, 64, "-1\n");
208         } else {
209                 r = snprintf(buf, 64, "%u\n", val);
210         }
211
212         return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
213 }
214
215 static ssize_t profiling_counter_src_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
216 {
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);
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
235         ret = kstrtol(buf, 10, &val);
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
275 static 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
282 static 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) {
296                 r = snprintf(buf, 64, "-1\n");
297         } else {
298                 r = snprintf(buf, 64, "%u\n", val);
299         }
300         return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
301 }
302
303 static 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
320         ret = kstrtol(buf, 10, &val);
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
330         mali_l2_cache_core_set_counter_src(l2_core, src_id, (u32)val);
331
332         *ppos += cnt;
333         return cnt;
334 }
335
336 static 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
354         ret = kstrtol(buf, 10, &val);
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) {
367                 mali_l2_cache_core_set_counter_src(l2_cache, src_id, (u32)val);
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
378 static 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
383 static 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
388 static 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
393 static 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
398 static 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
403 static 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
408 static 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
415 static 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
422 static const struct file_operations l2_all_counter_src0_fops = {
423         .owner = THIS_MODULE,
424         .write = l2_all_counter_src0_write,
425 };
426
427 static const struct file_operations l2_all_counter_src1_fops = {
428         .owner = THIS_MODULE,
429         .write = l2_all_counter_src1_write,
430 };
431
432 static 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
460 static 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
465 static 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
470 static 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
476 static 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
482 static 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
494         ret = kstrtoul(buf, 10, &val);
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;
502                 _mali_osk_pm_dev_ref_get_sync();
503         } else if (0 == val && MALI_TRUE == power_always_on_enabled) {
504                 power_always_on_enabled = MALI_FALSE;
505                 _mali_osk_pm_dev_ref_put();
506         }
507
508         *ppos += cnt;
509         return cnt;
510 }
511
512 static 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
521 static 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
527 static ssize_t power_power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
528 {
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)) {
532                 mali_pm_os_resume();
533         } else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_DVFS_PAUSE], strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE])-1)) {
534                 mali_dev_pause();
535         } else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_DVFS_RESUME], strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME])-1)) {
536                 mali_dev_resume();
537         }
538         *ppos += cnt;
539         return cnt;
540 }
541
542 static 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
548 static 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
555 static 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
563         if (!size) {
564                 return -ENOMEM;
565         }
566
567         /* Create the internal state dump. */
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);
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
578 static 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
583 static 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)
593 static 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
598         r = snprintf(buf, 64, "%u\n", _mali_internal_profiling_is_recording() ? 1 : 0);
599         return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
600 }
601
602 static 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
618         ret = kstrtoul(buf, 10, &val);
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
662 static const struct file_operations profiling_record_fops = {
663         .owner = THIS_MODULE,
664         .read  = profiling_record_read,
665         .write = profiling_record_write,
666 };
667
668 static 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
686 static 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
704 static void profiling_events_stop(struct seq_file *s, void *v)
705 {
706         kfree(v);
707 }
708
709 static 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
717         index = (u32) * spos;
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
728 static 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
739         index = (u32) * spos;
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
751                 switch (event_id & 0x0F000000) {
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
772                 switch (event_id & 0x00FF0000) {
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)) {
813                                 switch (event_id & 0x0000FFFF) {
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
839 static 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
846 static int profiling_events_open(struct inode *inode, struct file *file)
847 {
848         return seq_open(file, &profiling_events_seq_ops);
849 }
850
851 static 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
859 static 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
866 static 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
871 static 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
881 static int memory_debugfs_show(struct seq_file *s, void *private_data)
882 {
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 }
890
891 static int memory_debugfs_open(struct inode *inode, struct file *file)
892 {
893         return single_open(file, memory_debugfs_show, inode->i_private);
894 }
895
896 static const struct file_operations memory_usage_fops = {
897         .owner = THIS_MODULE,
898         .open = memory_debugfs_open,
899         .read  = seq_read,
900         .llseek = seq_lseek,
901         .release = single_release,
902 };
903
904 static 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;
908         u32 uval = _mali_ukk_utilization_gp_pp();
909
910         r = snprintf(buf, 64, "%u\n", uval);
911         return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
912 }
913
914 static 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;
918         u32 uval = _mali_ukk_utilization_gp();
919
920         r = snprintf(buf, 64, "%u\n", uval);
921         return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
922 }
923
924 static 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;
928         u32 uval = _mali_ukk_utilization_pp();
929
930         r = snprintf(buf, 64, "%u\n", uval);
931         return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
932 }
933
934
935 static const struct file_operations utilization_gp_pp_fops = {
936         .owner = THIS_MODULE,
937         .read = utilization_gp_pp_read,
938 };
939
940 static const struct file_operations utilization_gp_fops = {
941         .owner = THIS_MODULE,
942         .read = utilization_gp_read,
943 };
944
945 static const struct file_operations utilization_pp_fops = {
946         .owner = THIS_MODULE,
947         .read = utilization_pp_read,
948 };
949
950 static 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
963         ret = kstrtoul(buf, 10, &val);
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
976 static 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
990 static 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
997 static 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) {
1002                 long i;
1003                 for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++) {
1004                         debugfs_create_file(_mali_uk_user_setting_descriptions[i],
1005                                             0600, mali_user_settings_dir, (void *)i,
1006                                             &user_settings_fops);
1007                 }
1008         }
1009
1010         return 0;
1011 }
1012
1013 static 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
1028         ret = kstrtoul(&buffer[0], 10, &val);
1029         if (0 != ret) {
1030                 return -EINVAL;
1031         }
1032
1033         ret = mali_executor_set_perf_level(val, MALI_TRUE); /* override even if core scaling is disabled */
1034         if (ret) {
1035                 return ret;
1036         }
1037
1038         *offp += count;
1039         return count;
1040 }
1041
1042 static 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
1047         r = snprintf(buffer, 64, "%u\n", mali_executor_get_num_cores_enabled());
1048
1049         return simple_read_from_buffer(buf, count, offp, buffer, r);
1050 }
1051
1052 static 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
1059 static 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
1064         r = snprintf(buffer, 64, "%u\n", mali_executor_get_num_cores_total());
1065
1066         return simple_read_from_buffer(buf, count, offp, buffer, r);
1067 }
1068
1069 static const struct file_operations pp_num_cores_total_fops = {
1070         .owner = THIS_MODULE,
1071         .read = pp_num_cores_total_read,
1072 };
1073
1074 static 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
1089         ret = kstrtoul(&buffer[0], 10, &val);
1090         if (0 != ret) {
1091                 return -EINVAL;
1092         }
1093
1094         switch (val) {
1095         case 1:
1096                 mali_executor_core_scaling_enable();
1097                 break;
1098         case 0:
1099                 mali_executor_core_scaling_disable();
1100                 break;
1101         default:
1102                 return -EINVAL;
1103                 break;
1104         }
1105
1106         *offp += count;
1107         return count;
1108 }
1109
1110 static ssize_t pp_core_scaling_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1111 {
1112         return simple_read_from_buffer(buf, count, offp, mali_executor_core_scaling_is_enabled() ? "1\n" : "0\n", 2);
1113 }
1114 static 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
1121 static 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:
1128                 r = snprintf(buffer, 64, "Mali-200\n");
1129                 break;
1130         case _MALI_PRODUCT_ID_MALI300:
1131                 r = snprintf(buffer, 64, "Mali-300\n");
1132                 break;
1133         case _MALI_PRODUCT_ID_MALI400:
1134                 r = snprintf(buffer, 64, "Mali-400 MP\n");
1135                 break;
1136         case _MALI_PRODUCT_ID_MALI450:
1137                 r = snprintf(buffer, 64, "Mali-450 MP\n");
1138                 break;
1139         case _MALI_PRODUCT_ID_UNKNOWN:
1140                 return -EINVAL;
1141                 break;
1142         };
1143
1144         return simple_read_from_buffer(buf, count, offp, buffer, r);
1145 }
1146
1147 static const struct file_operations version_fops = {
1148         .owner = THIS_MODULE,
1149         .read = version_read,
1150 };
1151
1152 #if defined(DEBUG)
1153 static int timeline_debugfs_show(struct seq_file *s, void *private_data)
1154 {
1155         struct mali_session_data *session, *tmp;
1156         u32 session_seq = 1;
1157
1158         seq_printf(s, "timeline system info: \n=================\n\n");
1159
1160         mali_session_lock();
1161         MALI_SESSION_FOREACH(session, tmp, link) {
1162                 seq_printf(s, "session %d <%p> start:\n", session_seq, session);
1163                 mali_timeline_debug_print_system(session->timeline_system, s);
1164                 seq_printf(s, "session %d end\n\n\n", session_seq++);
1165         }
1166         mali_session_unlock();
1167
1168         return 0;
1169 }
1170
1171 static int timeline_debugfs_open(struct inode *inode, struct file *file)
1172 {
1173         return single_open(file, timeline_debugfs_show, inode->i_private);
1174 }
1175
1176 static const struct file_operations timeline_dump_fops = {
1177         .owner = THIS_MODULE,
1178         .open = timeline_debugfs_open,
1179         .read  = seq_read,
1180         .llseek = seq_lseek,
1181         .release = single_release
1182 };
1183 #endif
1184
1185 int mali_sysfs_register(const char *mali_dev_name)
1186 {
1187         mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
1188         if (ERR_PTR(-ENODEV) == mali_debugfs_dir) {
1189                 /* Debugfs not supported. */
1190                 mali_debugfs_dir = NULL;
1191         } else {
1192                 if (NULL != mali_debugfs_dir) {
1193                         /* Debugfs directory created successfully; create files now */
1194                         struct dentry *mali_power_dir;
1195                         struct dentry *mali_gp_dir;
1196                         struct dentry *mali_pp_dir;
1197                         struct dentry *mali_l2_dir;
1198                         struct dentry *mali_profiling_dir;
1199
1200                         debugfs_create_file("version", 0400, mali_debugfs_dir, NULL, &version_fops);
1201
1202                         mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
1203                         if (mali_power_dir != NULL) {
1204                                 debugfs_create_file("always_on", 0600, mali_power_dir, NULL, &power_always_on_fops);
1205                                 debugfs_create_file("power_events", 0200, mali_power_dir, NULL, &power_power_events_fops);
1206                         }
1207
1208                         mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
1209                         if (mali_gp_dir != NULL) {
1210                                 u32 num_groups;
1211                                 long i;
1212
1213                                 num_groups = mali_group_get_glob_num_groups();
1214                                 for (i = 0; i < num_groups; i++) {
1215                                         struct mali_group *group = mali_group_get_glob_group(i);
1216
1217                                         struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
1218                                         if (NULL != gp_core) {
1219                                                 struct dentry *mali_gp_gpx_dir;
1220                                                 mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
1221                                                 if (NULL != mali_gp_gpx_dir) {
1222                                                         debugfs_create_file("base_addr", 0400, mali_gp_gpx_dir, &gp_core->hw_core, &hw_core_base_addr_fops);
1223                                                         debugfs_create_file("enabled", 0600, mali_gp_gpx_dir, group, &group_enabled_fops);
1224                                                 }
1225                                                 break; /* no need to look for any other GP cores */
1226                                         }
1227
1228                                 }
1229                         }
1230
1231                         mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir);
1232                         if (mali_pp_dir != NULL) {
1233                                 u32 num_groups;
1234                                 long i;
1235
1236                                 debugfs_create_file("num_cores_total", 0400, mali_pp_dir, NULL, &pp_num_cores_total_fops);
1237                                 debugfs_create_file("num_cores_enabled", 0600, mali_pp_dir, NULL, &pp_num_cores_enabled_fops);
1238                                 debugfs_create_file("core_scaling_enabled", 0600, mali_pp_dir, NULL, &pp_core_scaling_enabled_fops);
1239
1240                                 num_groups = mali_group_get_glob_num_groups();
1241                                 for (i = 0; i < num_groups; i++) {
1242                                         struct mali_group *group = mali_group_get_glob_group(i);
1243
1244                                         struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
1245                                         if (NULL != pp_core) {
1246                                                 char buf[16];
1247                                                 struct dentry *mali_pp_ppx_dir;
1248                                                 _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
1249                                                 mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
1250                                                 if (NULL != mali_pp_ppx_dir) {
1251                                                         debugfs_create_file("base_addr", 0400, mali_pp_ppx_dir, &pp_core->hw_core, &hw_core_base_addr_fops);
1252                                                         if (!mali_group_is_virtual(group)) {
1253                                                                 debugfs_create_file("enabled", 0600, mali_pp_ppx_dir, group, &group_enabled_fops);
1254                                                         }
1255                                                 }
1256                                         }
1257                                 }
1258                         }
1259
1260                         mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir);
1261                         if (mali_l2_dir != NULL) {
1262                                 struct dentry *mali_l2_all_dir;
1263                                 u32 l2_id;
1264                                 struct mali_l2_cache_core *l2_cache;
1265
1266                                 mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir);
1267                                 if (mali_l2_all_dir != NULL) {
1268                                         debugfs_create_file("counter_src0", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops);
1269                                         debugfs_create_file("counter_src1", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops);
1270                                 }
1271
1272                                 l2_id = 0;
1273                                 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1274                                 while (NULL != l2_cache) {
1275                                         char buf[16];
1276                                         struct dentry *mali_l2_l2x_dir;
1277                                         _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id);
1278                                         mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir);
1279                                         if (NULL != mali_l2_l2x_dir) {
1280                                                 debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops);
1281                                                 debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops);
1282                                                 debugfs_create_file("counter_val0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_val0_fops);
1283                                                 debugfs_create_file("counter_val1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_val1_fops);
1284                                                 debugfs_create_file("base_addr", 0400, mali_l2_l2x_dir, &l2_cache->hw_core, &hw_core_base_addr_fops);
1285                                         }
1286
1287                                         /* try next L2 */
1288                                         l2_id++;
1289                                         l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1290                                 }
1291                         }
1292
1293                         debugfs_create_file("gpu_memory", 0444, mali_debugfs_dir, NULL, &memory_usage_fops);
1294
1295                         debugfs_create_file("utilization_gp_pp", 0400, mali_debugfs_dir, NULL, &utilization_gp_pp_fops);
1296                         debugfs_create_file("utilization_gp", 0400, mali_debugfs_dir, NULL, &utilization_gp_fops);
1297                         debugfs_create_file("utilization_pp", 0400, mali_debugfs_dir, NULL, &utilization_pp_fops);
1298
1299                         mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
1300                         if (mali_profiling_dir != NULL) {
1301                                 u32 max_sub_jobs;
1302                                 long i;
1303                                 struct dentry *mali_profiling_gp_dir;
1304                                 struct dentry *mali_profiling_pp_dir;
1305 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1306                                 struct dentry *mali_profiling_proc_dir;
1307 #endif
1308                                 /*
1309                                  * Create directory where we can set GP HW counters.
1310                                  */
1311                                 mali_profiling_gp_dir = debugfs_create_dir("gp", mali_profiling_dir);
1312                                 if (mali_profiling_gp_dir != NULL) {
1313                                         debugfs_create_file("counter_src0", 0600, mali_profiling_gp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_GP(0), &profiling_counter_src_fops);
1314                                         debugfs_create_file("counter_src1", 0600, mali_profiling_gp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_GP(1), &profiling_counter_src_fops);
1315                                 }
1316
1317                                 /*
1318                                  * Create directory where we can set PP HW counters.
1319                                  * Possible override with specific HW counters for a particular sub job
1320                                  * (Disable core scaling before using the override!)
1321                                  */
1322                                 mali_profiling_pp_dir = debugfs_create_dir("pp", mali_profiling_dir);
1323                                 if (mali_profiling_pp_dir != NULL) {
1324                                         debugfs_create_file("counter_src0", 0600, mali_profiling_pp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_PP(0), &profiling_counter_src_fops);
1325                                         debugfs_create_file("counter_src1", 0600, mali_profiling_pp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_PP(1), &profiling_counter_src_fops);
1326                                 }
1327
1328                                 max_sub_jobs = mali_executor_get_num_cores_total();
1329                                 for (i = 0; i < max_sub_jobs; i++) {
1330                                         char buf[16];
1331                                         struct dentry *mali_profiling_pp_x_dir;
1332                                         _mali_osk_snprintf(buf, sizeof(buf), "%u", i);
1333                                         mali_profiling_pp_x_dir = debugfs_create_dir(buf, mali_profiling_pp_dir);
1334                                         if (NULL != mali_profiling_pp_x_dir) {
1335                                                 debugfs_create_file("counter_src0",
1336                                                                     0600, mali_profiling_pp_x_dir,
1337                                                                     (void *)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(0, i),
1338                                                                     &profiling_counter_src_fops);
1339                                                 debugfs_create_file("counter_src1",
1340                                                                     0600, mali_profiling_pp_x_dir,
1341                                                                     (void *)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(1, i),
1342                                                                     &profiling_counter_src_fops);
1343                                         }
1344                                 }
1345
1346 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1347                                 mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir);
1348                                 if (mali_profiling_proc_dir != NULL) {
1349                                         struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir);
1350                                         if (mali_profiling_proc_default_dir != NULL) {
1351                                                 debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void *)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops);
1352                                         }
1353                                 }
1354                                 debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
1355                                 debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops);
1356                                 debugfs_create_file("events_human_readable", 0400, mali_profiling_dir, NULL, &profiling_events_human_readable_fops);
1357 #endif
1358                         }
1359
1360 #if MALI_STATE_TRACKING
1361                         debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
1362 #endif
1363
1364 #if defined(DEBUG)
1365                         debugfs_create_file("timeline_dump", 0400, mali_debugfs_dir, NULL, &timeline_dump_fops);
1366 #endif
1367                         if (mali_sysfs_user_settings_register()) {
1368                                 /* Failed to create the debugfs entries for the user settings DB. */
1369                                 MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n"));
1370                         }
1371                 }
1372         }
1373
1374         /* Success! */
1375         return 0;
1376 }
1377
1378 int mali_sysfs_unregister(void)
1379 {
1380         if (NULL != mali_debugfs_dir) {
1381                 debugfs_remove_recursive(mali_debugfs_dir);
1382         }
1383         return 0;
1384 }
1385
1386 #else /* MALI_LICENSE_IS_GPL */
1387
1388 /* Dummy implementations for non-GPL */
1389
1390 int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
1391 {
1392         return 0;
1393 }
1394
1395 int mali_sysfs_unregister(void)
1396 {
1397         return 0;
1398 }
1399
1400 #endif /* MALI_LICENSE_IS_GPL */