2 * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
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.
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.
12 * @file mali_kernel_sysfs.c
13 * Implementation of some sysfs data exports
16 #include <linux/kernel.h>
18 #include <linux/device.h>
19 #include <linux/module.h>
20 #include "mali_kernel_license.h"
21 #include "mali_kernel_common.h"
24 #if MALI_LICENSE_IS_GPL
26 #include <linux/seq_file.h>
27 #include <linux/debugfs.h>
28 #include <asm/uaccess.h>
29 #include <linux/module.h>
30 #include "mali_kernel_sysfs.h"
31 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
32 #include <linux/slab.h>
33 #include "mali_osk_profiling.h"
36 #include "mali_group.h"
39 #include "mali_l2_cache.h"
40 #include "mali_hw_core.h"
41 #include "mali_kernel_core.h"
42 #include "mali_user_settings_db.h"
43 #include "mali_device_pause_resume.h"
44 #include "mali_profiling_internal.h"
45 #include "mali_gp_job.h"
46 #include "mali_pp_job.h"
48 #define POWER_BUFFER_SIZE 3
50 static struct dentry *mali_debugfs_dir = NULL;
56 _MALI_DEVICE_DVFS_PAUSE,
57 _MALI_DEVICE_DVFS_RESUME,
59 } _mali_device_debug_power_events;
61 static const char* const mali_power_events[_MALI_MAX_EVENTS] = {
62 [_MALI_DEVICE_SUSPEND] = "suspend",
63 [_MALI_DEVICE_RESUME] = "resume",
64 [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause",
65 [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume",
68 static u32 virtual_power_status_register = 0;
69 static char pwr_buf[POWER_BUFFER_SIZE];
71 static mali_bool power_always_on_enabled = MALI_FALSE;
73 static int open_copy_private_data(struct inode *inode, struct file *filp)
75 filp->private_data = inode->i_private;
79 static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
87 val = mali_gp_job_get_gp_counter_src0();
91 val = mali_gp_job_get_gp_counter_src1();
94 if (MALI_HW_CORE_NO_COUNTER == val)
96 r = sprintf(buf, "-1\n");
100 r = sprintf(buf, "%u\n", val);
102 return simple_read_from_buffer(ubuf, cnt, gpos, buf, r);
105 static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
111 if (cnt >= sizeof(buf))
116 if (copy_from_user(&buf, ubuf, cnt))
123 ret = strict_strtol(buf, 10, &val);
131 /* any negative input will disable counter */
132 val = MALI_HW_CORE_NO_COUNTER;
137 if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val))
144 if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val))
154 static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
162 if (cnt >= sizeof(buf))
167 if (copy_from_user(&buf, ubuf, cnt))
174 ret = strict_strtol(buf, 10, &val);
182 /* any negative input will disable counter */
183 val = MALI_HW_CORE_NO_COUNTER;
186 num_groups = mali_group_get_glob_num_groups();
187 for (i = 0; i < num_groups; i++)
189 struct mali_group *group = mali_group_get_glob_group(i);
191 struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
196 if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val))
203 if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val))
215 static ssize_t gp_gpx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
217 return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 0);
220 static ssize_t gp_gpx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
222 return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 1);
225 static ssize_t gp_gpx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
227 return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
230 static ssize_t gp_gpx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
232 return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
235 static ssize_t gp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
237 return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
240 static ssize_t gp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
242 return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
245 static const struct file_operations gp_gpx_counter_src0_fops = {
246 .owner = THIS_MODULE,
247 .open = open_copy_private_data,
248 .read = gp_gpx_counter_src0_read,
249 .write = gp_gpx_counter_src0_write,
252 static const struct file_operations gp_gpx_counter_src1_fops = {
253 .owner = THIS_MODULE,
254 .open = open_copy_private_data,
255 .read = gp_gpx_counter_src1_read,
256 .write = gp_gpx_counter_src1_write,
259 static const struct file_operations gp_all_counter_src0_fops = {
260 .owner = THIS_MODULE,
261 .write = gp_all_counter_src0_write,
264 static const struct file_operations gp_all_counter_src1_fops = {
265 .owner = THIS_MODULE,
266 .write = gp_all_counter_src1_write,
269 static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
277 val = mali_pp_job_get_pp_counter_src0();
281 val = mali_pp_job_get_pp_counter_src1();
284 if (MALI_HW_CORE_NO_COUNTER == val)
286 r = sprintf(buf, "-1\n");
290 r = sprintf(buf, "%u\n", val);
292 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
295 static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
301 if (cnt >= sizeof(buf))
306 if (copy_from_user(&buf, ubuf, cnt))
313 ret = strict_strtol(buf, 10, &val);
321 /* any negative input will disable counter */
322 val = MALI_HW_CORE_NO_COUNTER;
327 if (MALI_TRUE != mali_pp_job_set_pp_counter_src0((u32)val))
334 if (MALI_TRUE != mali_pp_job_set_pp_counter_src1((u32)val))
344 static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
352 if (cnt >= sizeof(buf))
357 if (copy_from_user(&buf, ubuf, cnt))
364 ret = strict_strtol(buf, 10, &val);
372 /* any negative input will disable counter */
373 val = MALI_HW_CORE_NO_COUNTER;
376 num_groups = mali_group_get_glob_num_groups();
377 for (i = 0; i < num_groups; i++)
379 struct mali_group *group = mali_group_get_glob_group(i);
381 struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
386 if (MALI_TRUE != mali_pp_job_set_pp_counter_src0((u32)val))
393 if (MALI_TRUE != mali_pp_job_set_pp_counter_src1((u32)val))
405 static ssize_t pp_ppx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
407 return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
410 static ssize_t pp_ppx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
412 return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
415 static ssize_t pp_ppx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
417 return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
420 static ssize_t pp_ppx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
422 return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
425 static ssize_t pp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
427 return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
430 static ssize_t pp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
432 return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
435 static const struct file_operations pp_ppx_counter_src0_fops = {
436 .owner = THIS_MODULE,
437 .open = open_copy_private_data,
438 .read = pp_ppx_counter_src0_read,
439 .write = pp_ppx_counter_src0_write,
442 static const struct file_operations pp_ppx_counter_src1_fops = {
443 .owner = THIS_MODULE,
444 .open = open_copy_private_data,
445 .read = pp_ppx_counter_src1_read,
446 .write = pp_ppx_counter_src1_write,
449 static const struct file_operations pp_all_counter_src0_fops = {
450 .owner = THIS_MODULE,
451 .write = pp_all_counter_src0_write,
454 static const struct file_operations pp_all_counter_src1_fops = {
455 .owner = THIS_MODULE,
456 .write = pp_all_counter_src1_write,
459 static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
464 struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
468 val = mali_l2_cache_core_get_counter_src0(l2_core);
472 val = mali_l2_cache_core_get_counter_src1(l2_core);
475 if (MALI_HW_CORE_NO_COUNTER == val)
477 r = sprintf(buf, "-1\n");
481 r = sprintf(buf, "%u\n", val);
483 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
486 static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
488 struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
493 if (cnt >= sizeof(buf))
498 if (copy_from_user(&buf, ubuf, cnt))
505 ret = strict_strtol(buf, 10, &val);
513 /* any negative input will disable counter */
514 val = MALI_HW_CORE_NO_COUNTER;
519 if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_core, (u32)val))
526 if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_core, (u32)val))
536 static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
542 struct mali_l2_cache_core *l2_cache;
544 if (cnt >= sizeof(buf))
549 if (copy_from_user(&buf, ubuf, cnt))
556 ret = strict_strtol(buf, 10, &val);
564 /* any negative input will disable counter */
565 val = MALI_HW_CORE_NO_COUNTER;
569 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
570 while (NULL != l2_cache)
574 if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val))
581 if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val))
589 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
596 static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
598 return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
601 static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
603 return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
606 static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
608 return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
611 static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
613 return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
616 static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
618 return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
621 static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
623 return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
626 static const struct file_operations l2_l2x_counter_src0_fops = {
627 .owner = THIS_MODULE,
628 .open = open_copy_private_data,
629 .read = l2_l2x_counter_src0_read,
630 .write = l2_l2x_counter_src0_write,
633 static const struct file_operations l2_l2x_counter_src1_fops = {
634 .owner = THIS_MODULE,
635 .open = open_copy_private_data,
636 .read = l2_l2x_counter_src1_read,
637 .write = l2_l2x_counter_src1_write,
640 static const struct file_operations l2_all_counter_src0_fops = {
641 .owner = THIS_MODULE,
642 .write = l2_all_counter_src0_write,
645 static const struct file_operations l2_all_counter_src1_fops = {
646 .owner = THIS_MODULE,
647 .write = l2_all_counter_src1_write,
650 static ssize_t power_always_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
656 cnt = min(cnt, sizeof(buf) - 1);
657 if (copy_from_user(buf, ubuf, cnt))
663 ret = strict_strtoul(buf, 10, &val);
669 /* Update setting (not exactly thread safe) */
670 if (1 == val && MALI_FALSE == power_always_on_enabled)
672 power_always_on_enabled = MALI_TRUE;
673 _mali_osk_pm_dev_ref_add();
675 else if (0 == val && MALI_TRUE == power_always_on_enabled)
677 power_always_on_enabled = MALI_FALSE;
678 _mali_osk_pm_dev_ref_dec();
685 static ssize_t power_always_on_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
687 if (MALI_TRUE == power_always_on_enabled)
689 return simple_read_from_buffer(ubuf, cnt, ppos, "1\n", 2);
693 return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2);
697 static const struct file_operations power_always_on_fops = {
698 .owner = THIS_MODULE,
699 .read = power_always_on_read,
700 .write = power_always_on_write,
703 static ssize_t power_power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
706 if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND])))
708 mali_pm_os_suspend();
709 /* @@@@ assuming currently suspend is successful later on to tune as per previous*/
710 virtual_power_status_register =1;
713 else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME])))
717 /* @@@@ assuming currently resume is successful later on to tune as per previous */
718 virtual_power_status_register = 1;
720 else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE])))
723 mali_dev_pause(&power_on);
726 virtual_power_status_register = 2;
731 /* @@@@ assuming currently resume is successful later on to tune as per previous */
732 virtual_power_status_register =1;
735 else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME])))
738 /* @@@@ assuming currently resume is successful later on to tune as per previous */
739 virtual_power_status_register = 1;
742 sprintf(pwr_buf, "%d",virtual_power_status_register);
746 static ssize_t power_power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
748 return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE);
751 static loff_t power_power_events_seek(struct file *file, loff_t offset, int orig)
753 file->f_pos = offset;
757 static const struct file_operations power_power_events_fops = {
758 .owner = THIS_MODULE,
759 .read = power_power_events_read,
760 .write = power_power_events_write,
761 .llseek = power_power_events_seek,
764 #if MALI_STATE_TRACKING
765 static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
771 size = seq_get_buf(seq_file, &buf);
778 /* Create the internal state dump. */
779 len = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING);
780 len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE);
782 len += _mali_kernel_core_dump_state(buf + len, size - len);
784 seq_commit(seq_file, len);
789 static int mali_seq_internal_state_open(struct inode *inode, struct file *file)
791 return single_open(file, mali_seq_internal_state_show, NULL);
794 static const struct file_operations mali_seq_internal_state_fops = {
795 .owner = THIS_MODULE,
796 .open = mali_seq_internal_state_open,
799 .release = single_release,
801 #endif /* MALI_STATE_TRACKING */
803 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
804 static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
809 r = sprintf(buf, "%u\n", _mali_internal_profiling_is_recording() ? 1 : 0);
810 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
813 static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
819 if (cnt >= sizeof(buf))
824 if (copy_from_user(&buf, ubuf, cnt))
831 ret = strict_strtoul(buf, 10, &val);
839 u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */
841 /* check if we are already recording */
842 if (MALI_TRUE == _mali_internal_profiling_is_recording())
844 MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n"));
848 /* check if we need to clear out an old recording first */
849 if (MALI_TRUE == _mali_internal_profiling_have_recording())
851 if (_MALI_OSK_ERR_OK != _mali_internal_profiling_clear())
853 MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n"));
858 /* start recording profiling data */
859 if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit))
861 MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n"));
865 MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit));
869 /* stop recording profiling data */
871 if (_MALI_OSK_ERR_OK != _mali_internal_profiling_stop(&count))
873 MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n"));
877 MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count));
884 static const struct file_operations profiling_record_fops = {
885 .owner = THIS_MODULE,
886 .read = profiling_record_read,
887 .write = profiling_record_write,
890 static void *profiling_events_start(struct seq_file *s, loff_t *pos)
894 /* check if we have data avaiable */
895 if (MALI_TRUE != _mali_internal_profiling_have_recording())
900 spos = kmalloc(sizeof(loff_t), GFP_KERNEL);
910 static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos)
914 /* check if we have data avaiable */
915 if (MALI_TRUE != _mali_internal_profiling_have_recording())
920 /* check if the next entry actually is avaiable */
921 if (_mali_internal_profiling_get_count() <= (u32)(*spos + 1))
930 static void profiling_events_stop(struct seq_file *s, void *v)
935 static int profiling_events_show(struct seq_file *seq_file, void *v)
945 /* Retrieve all events */
946 if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, ×tamp, &event_id, data))
948 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]);
955 static int profiling_events_show_human_readable(struct seq_file *seq_file, void *v)
957 #define MALI_EVENT_ID_IS_HW(event_id) (((event_id & 0x00FF0000) >= MALI_PROFILING_EVENT_CHANNEL_GP0) && ((event_id & 0x00FF0000) <= MALI_PROFILING_EVENT_CHANNEL_PP7))
959 static u64 start_time = 0;
968 /* Retrieve all events */
969 if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, ×tamp, &event_id, data))
971 seq_printf(seq_file, "%llu %u %u %u %u %u %u # ", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
975 start_time = timestamp;
978 seq_printf(seq_file, "[%06u] ", index);
980 switch(event_id & 0x0F000000)
982 case MALI_PROFILING_EVENT_TYPE_SINGLE:
983 seq_printf(seq_file, "SINGLE | ");
985 case MALI_PROFILING_EVENT_TYPE_START:
986 seq_printf(seq_file, "START | ");
988 case MALI_PROFILING_EVENT_TYPE_STOP:
989 seq_printf(seq_file, "STOP | ");
991 case MALI_PROFILING_EVENT_TYPE_SUSPEND:
992 seq_printf(seq_file, "SUSPEND | ");
994 case MALI_PROFILING_EVENT_TYPE_RESUME:
995 seq_printf(seq_file, "RESUME | ");
998 seq_printf(seq_file, "0x%01X | ", (event_id & 0x0F000000) >> 24);
1002 switch(event_id & 0x00FF0000)
1004 case MALI_PROFILING_EVENT_CHANNEL_SOFTWARE:
1005 seq_printf(seq_file, "SW | ");
1007 case MALI_PROFILING_EVENT_CHANNEL_GP0:
1008 seq_printf(seq_file, "GP0 | ");
1010 case MALI_PROFILING_EVENT_CHANNEL_PP0:
1011 seq_printf(seq_file, "PP0 | ");
1013 case MALI_PROFILING_EVENT_CHANNEL_PP1:
1014 seq_printf(seq_file, "PP1 | ");
1016 case MALI_PROFILING_EVENT_CHANNEL_PP2:
1017 seq_printf(seq_file, "PP2 | ");
1019 case MALI_PROFILING_EVENT_CHANNEL_PP3:
1020 seq_printf(seq_file, "PP3 | ");
1022 case MALI_PROFILING_EVENT_CHANNEL_PP4:
1023 seq_printf(seq_file, "PP4 | ");
1025 case MALI_PROFILING_EVENT_CHANNEL_PP5:
1026 seq_printf(seq_file, "PP5 | ");
1028 case MALI_PROFILING_EVENT_CHANNEL_PP6:
1029 seq_printf(seq_file, "PP6 | ");
1031 case MALI_PROFILING_EVENT_CHANNEL_PP7:
1032 seq_printf(seq_file, "PP7 | ");
1034 case MALI_PROFILING_EVENT_CHANNEL_GPU:
1035 seq_printf(seq_file, "GPU | ");
1038 seq_printf(seq_file, "0x%02X | ", (event_id & 0x00FF0000) >> 16);
1042 if (MALI_EVENT_ID_IS_HW(event_id))
1044 if (((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_START) || ((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_STOP))
1046 switch(event_id & 0x0000FFFF)
1048 case MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL:
1049 seq_printf(seq_file, "PHYSICAL | ");
1051 case MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL:
1052 seq_printf(seq_file, "VIRTUAL | ");
1055 seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
1061 seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
1066 seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
1069 seq_printf(seq_file, "T0 + 0x%016llX\n", timestamp - start_time);
1077 static const struct seq_operations profiling_events_seq_ops = {
1078 .start = profiling_events_start,
1079 .next = profiling_events_next,
1080 .stop = profiling_events_stop,
1081 .show = profiling_events_show
1084 static int profiling_events_open(struct inode *inode, struct file *file)
1086 return seq_open(file, &profiling_events_seq_ops);
1089 static const struct file_operations profiling_events_fops = {
1090 .owner = THIS_MODULE,
1091 .open = profiling_events_open,
1093 .llseek = seq_lseek,
1094 .release = seq_release,
1097 static const struct seq_operations profiling_events_human_readable_seq_ops = {
1098 .start = profiling_events_start,
1099 .next = profiling_events_next,
1100 .stop = profiling_events_stop,
1101 .show = profiling_events_show_human_readable
1104 static int profiling_events_human_readable_open(struct inode *inode, struct file *file)
1106 return seq_open(file, &profiling_events_human_readable_seq_ops);
1109 static const struct file_operations profiling_events_human_readable_fops = {
1110 .owner = THIS_MODULE,
1111 .open = profiling_events_human_readable_open,
1113 .llseek = seq_lseek,
1114 .release = seq_release,
1119 static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
1123 u32 mem = _mali_ukk_report_memory_usage();
1125 r = snprintf(buf, 64, "%u\n", mem);
1126 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
1129 static const struct file_operations memory_usage_fops = {
1130 .owner = THIS_MODULE,
1131 .read = memory_used_read,
1134 static ssize_t utilization_gp_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
1138 u32 uval= _mali_ukk_utilization_gp_pp();
1140 r = snprintf(buf, 64, "%u\n", uval);
1141 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
1144 static ssize_t utilization_gp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
1148 u32 uval= _mali_ukk_utilization_gp();
1150 r = snprintf(buf, 64, "%u\n", uval);
1151 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
1154 static ssize_t utilization_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
1158 u32 uval= _mali_ukk_utilization_pp();
1160 r = snprintf(buf, 64, "%u\n", uval);
1161 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
1165 static const struct file_operations utilization_gp_pp_fops = {
1166 .owner = THIS_MODULE,
1167 .read = utilization_gp_pp_read,
1170 static const struct file_operations utilization_gp_fops = {
1171 .owner = THIS_MODULE,
1172 .read = utilization_gp_read,
1175 static const struct file_operations utilization_pp_fops = {
1176 .owner = THIS_MODULE,
1177 .read = utilization_pp_read,
1180 static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
1184 _mali_uk_user_setting_t setting;
1187 cnt = min(cnt, sizeof(buf) - 1);
1188 if (copy_from_user(buf, ubuf, cnt))
1194 ret = strict_strtoul(buf, 10, &val);
1200 /* Update setting */
1201 setting = (_mali_uk_user_setting_t)(filp->private_data);
1202 mali_set_user_setting(setting, val);
1208 static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
1213 _mali_uk_user_setting_t setting;
1215 setting = (_mali_uk_user_setting_t)(filp->private_data);
1216 value = mali_get_user_setting(setting);
1218 r = snprintf(buf, 64, "%u\n", value);
1219 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
1222 static const struct file_operations user_settings_fops = {
1223 .owner = THIS_MODULE,
1224 .open = open_copy_private_data,
1225 .read = user_settings_read,
1226 .write = user_settings_write,
1229 static int mali_sysfs_user_settings_register(void)
1231 struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir);
1233 if (mali_user_settings_dir != NULL)
1236 for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++)
1238 debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops);
1245 int mali_sysfs_register(const char *mali_dev_name)
1247 mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
1248 if(ERR_PTR(-ENODEV) == mali_debugfs_dir)
1250 /* Debugfs not supported. */
1251 mali_debugfs_dir = NULL;
1255 if(NULL != mali_debugfs_dir)
1257 /* Debugfs directory created successfully; create files now */
1258 struct dentry *mali_power_dir;
1259 struct dentry *mali_gp_dir;
1260 struct dentry *mali_pp_dir;
1261 struct dentry *mali_l2_dir;
1262 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1263 struct dentry *mali_profiling_dir;
1266 mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
1267 if (mali_power_dir != NULL)
1269 debugfs_create_file("always_on", 0400, mali_power_dir, NULL, &power_always_on_fops);
1270 debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_power_events_fops);
1273 mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
1274 if (mali_gp_dir != NULL)
1276 struct dentry *mali_gp_all_dir;
1280 mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir);
1281 if (mali_gp_all_dir != NULL)
1283 debugfs_create_file("counter_src0", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops);
1284 debugfs_create_file("counter_src1", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops);
1287 num_groups = mali_group_get_glob_num_groups();
1288 for (i = 0; i < num_groups; i++)
1290 struct mali_group *group = mali_group_get_glob_group(i);
1292 struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
1293 if (NULL != gp_core)
1295 struct dentry *mali_gp_gpx_dir;
1296 mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
1297 if (NULL != mali_gp_gpx_dir)
1299 debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops);
1300 debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops);
1302 break; /* no need to look for any other GP cores */
1308 mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir);
1309 if (mali_pp_dir != NULL)
1311 struct dentry *mali_pp_all_dir;
1315 mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir);
1316 if (mali_pp_all_dir != NULL)
1318 debugfs_create_file("counter_src0", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops);
1319 debugfs_create_file("counter_src1", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops);
1322 num_groups = mali_group_get_glob_num_groups();
1323 for (i = 0; i < num_groups; i++)
1325 struct mali_group *group = mali_group_get_glob_group(i);
1327 struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
1328 if (NULL != pp_core)
1331 struct dentry *mali_pp_ppx_dir;
1332 _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
1333 mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
1334 if (NULL != mali_pp_ppx_dir)
1336 debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops);
1337 debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops);
1343 mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir);
1344 if (mali_l2_dir != NULL)
1346 struct dentry *mali_l2_all_dir;
1348 struct mali_l2_cache_core *l2_cache;
1350 mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir);
1351 if (mali_l2_all_dir != NULL)
1353 debugfs_create_file("counter_src0", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops);
1354 debugfs_create_file("counter_src1", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops);
1358 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1359 while (NULL != l2_cache)
1362 struct dentry *mali_l2_l2x_dir;
1363 _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id);
1364 mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir);
1365 if (NULL != mali_l2_l2x_dir)
1367 debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops);
1368 debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops);
1373 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1377 debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops);
1379 debugfs_create_file("utilization_gp_pp", 0400, mali_debugfs_dir, NULL, &utilization_gp_pp_fops);
1380 debugfs_create_file("utilization_gp", 0400, mali_debugfs_dir, NULL, &utilization_gp_fops);
1381 debugfs_create_file("utilization_pp", 0400, mali_debugfs_dir, NULL, &utilization_pp_fops);
1383 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1384 mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
1385 if (mali_profiling_dir != NULL)
1387 struct dentry *mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir);
1388 if (mali_profiling_proc_dir != NULL)
1390 struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir);
1391 if (mali_profiling_proc_default_dir != NULL)
1393 debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void*)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops);
1396 debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
1397 debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops);
1398 debugfs_create_file("events_human_readable", 0400, mali_profiling_dir, NULL, &profiling_events_human_readable_fops);
1402 #if MALI_STATE_TRACKING
1403 debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
1406 if (mali_sysfs_user_settings_register())
1408 /* Failed to create the debugfs entries for the user settings DB. */
1409 MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n"));
1418 int mali_sysfs_unregister(void)
1420 if(NULL != mali_debugfs_dir)
1422 debugfs_remove_recursive(mali_debugfs_dir);
1429 /* Dummy implementations for non-GPL */
1431 int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
1436 int mali_sysfs_unregister(void)