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