ae4fad8d7588cc8fd6e4284236e46691cf14c024
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / linux / mali_kernel_linux.c
1 /**
2  * Copyright (C) 2010-2015 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_linux.c
14  * Implementation of the Linux device driver entrypoints
15  */
16 #include "../platform/rk30/custom_log.h"
17 #include "../platform/rk30/rk_ext.h"
18
19 #include <linux/module.h>   /* kernel module definitions */
20 #include <linux/fs.h>       /* file system operations */
21 #include <linux/cdev.h>     /* character device definitions */
22 #include <linux/mm.h>       /* memory manager definitions */
23 #include <linux/mali/mali_utgard_ioctl.h>
24 #include <linux/version.h>
25 #include <linux/device.h>
26 #include "mali_kernel_license.h"
27 #include <linux/platform_device.h>
28 #include <linux/miscdevice.h>
29 #include <linux/bug.h>
30 #include <linux/of.h>
31
32 #include <linux/mali/mali_utgard.h>
33 #include "mali_kernel_common.h"
34 #include "mali_session.h"
35 #include "mali_kernel_core.h"
36 #include "mali_osk.h"
37 #include "mali_kernel_linux.h"
38 #include "mali_ukk.h"
39 #include "mali_ukk_wrappers.h"
40 #include "mali_kernel_sysfs.h"
41 #include "mali_pm.h"
42 #include "mali_kernel_license.h"
43 #include "mali_memory.h"
44 #include "mali_memory_dma_buf.h"
45 #include "mali_memory_manager.h"
46 #include "mali_memory_swap_alloc.h"
47 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
48 #include "mali_profiling_internal.h"
49 #endif
50 #if defined(CONFIG_MALI400_PROFILING) && defined(CONFIG_MALI_DVFS)
51 #include "mali_osk_profiling.h"
52 #include "mali_dvfs_policy.h"
53
54 static int is_first_resume = 1;
55 /*Store the clk and vol for boot/insmod and mali_resume*/
56 static struct mali_gpu_clk_item mali_gpu_clk[2];
57 #endif
58
59 /* Streamline support for the Mali driver */
60 #if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_MALI400_PROFILING)
61 /* Ask Linux to create the tracepoints */
62 #define CREATE_TRACE_POINTS
63 #include "mali_linux_trace.h"
64
65 EXPORT_TRACEPOINT_SYMBOL_GPL(mali_timeline_event);
66 EXPORT_TRACEPOINT_SYMBOL_GPL(mali_hw_counter);
67 EXPORT_TRACEPOINT_SYMBOL_GPL(mali_sw_counters);
68 #endif /* CONFIG_TRACEPOINTS */
69
70 /* from the __malidrv_build_info.c file that is generated during build */
71 extern const char *__malidrv_build_info(void);
72
73 /* Module parameter to control log level */
74 int mali_debug_level = 2;
75 module_param(mali_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */
76 MODULE_PARM_DESC(mali_debug_level, "Higher number, more dmesg output");
77
78 extern int mali_max_job_runtime;
79 module_param(mali_max_job_runtime, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
80 MODULE_PARM_DESC(mali_max_job_runtime, "Maximum allowed job runtime in msecs.\nJobs will be killed after this no matter what");
81
82 extern int mali_l2_max_reads;
83 module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH);
84 MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache");
85
86 extern unsigned int mali_dedicated_mem_start;
87 module_param(mali_dedicated_mem_start, uint, S_IRUSR | S_IRGRP | S_IROTH);
88 MODULE_PARM_DESC(mali_dedicated_mem_start, "Physical start address of dedicated Mali GPU memory.");
89
90 extern unsigned int mali_dedicated_mem_size;
91 module_param(mali_dedicated_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH);
92 MODULE_PARM_DESC(mali_dedicated_mem_size, "Size of dedicated Mali GPU memory.");
93
94 extern unsigned int mali_shared_mem_size;
95 module_param(mali_shared_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH);
96 MODULE_PARM_DESC(mali_shared_mem_size, "Size of shared Mali GPU memory.");
97
98 #if defined(CONFIG_MALI400_PROFILING)
99 extern int mali_boot_profiling;
100 module_param(mali_boot_profiling, int, S_IRUSR | S_IRGRP | S_IROTH);
101 MODULE_PARM_DESC(mali_boot_profiling, "Start profiling as a part of Mali driver initialization");
102 #endif
103
104 extern int mali_max_pp_cores_group_1;
105 module_param(mali_max_pp_cores_group_1, int, S_IRUSR | S_IRGRP | S_IROTH);
106 MODULE_PARM_DESC(mali_max_pp_cores_group_1, "Limit the number of PP cores to use from first PP group.");
107
108 extern int mali_max_pp_cores_group_2;
109 module_param(mali_max_pp_cores_group_2, int, S_IRUSR | S_IRGRP | S_IROTH);
110 MODULE_PARM_DESC(mali_max_pp_cores_group_2, "Limit the number of PP cores to use from second PP group (Mali-450 only).");
111
112 extern unsigned int mali_mem_swap_out_threshold_value;
113 module_param(mali_mem_swap_out_threshold_value, uint, S_IRUSR | S_IRGRP | S_IROTH);
114 MODULE_PARM_DESC(mali_mem_swap_out_threshold_value, "Threshold value used to limit how much swappable memory cached in Mali driver.");
115
116 #if defined(CONFIG_MALI_DVFS)
117 /** the max fps the same as display vsync default 60, can set by module insert parameter */
118 extern int mali_max_system_fps;
119 module_param(mali_max_system_fps, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
120 MODULE_PARM_DESC(mali_max_system_fps, "Max system fps the same as display VSYNC.");
121
122 /** a lower limit on their desired FPS default 58, can set by module insert parameter*/
123 extern int mali_desired_fps;
124 module_param(mali_desired_fps, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
125 MODULE_PARM_DESC(mali_desired_fps, "A bit lower than max_system_fps which user desired fps");
126 #endif
127
128 #if MALI_ENABLE_CPU_CYCLES
129 #include <linux/cpumask.h>
130 #include <linux/timer.h>
131 #include <asm/smp.h>
132 static struct timer_list mali_init_cpu_clock_timers[8];
133 static u32 mali_cpu_clock_last_value[8] = {0,};
134 #endif
135
136 /* Export symbols from common code: mali_user_settings.c */
137 #include "mali_user_settings_db.h"
138 EXPORT_SYMBOL(mali_set_user_setting);
139 EXPORT_SYMBOL(mali_get_user_setting);
140
141 static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */
142
143 /* This driver only supports one Mali device, and this variable stores this single platform device */
144 struct platform_device *mali_platform_device = NULL;
145
146 /* This driver only supports one Mali device, and this variable stores the exposed misc device (/dev/mali) */
147 static struct miscdevice mali_miscdevice = { 0, };
148
149 static int mali_miscdevice_register(struct platform_device *pdev);
150 static void mali_miscdevice_unregister(void);
151
152 static int mali_open(struct inode *inode, struct file *filp);
153 static int mali_release(struct inode *inode, struct file *filp);
154 #ifdef HAVE_UNLOCKED_IOCTL
155 static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
156 #else
157 static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
158 #endif
159
160 static int mali_probe(struct platform_device *pdev);
161 static int mali_remove(struct platform_device *pdev);
162
163 static int mali_driver_suspend_scheduler(struct device *dev);
164 static int mali_driver_resume_scheduler(struct device *dev);
165
166 #ifdef CONFIG_PM_RUNTIME
167 static int mali_driver_runtime_suspend(struct device *dev);
168 static int mali_driver_runtime_resume(struct device *dev);
169 static int mali_driver_runtime_idle(struct device *dev);
170 #endif
171
172 #if defined(MALI_FAKE_PLATFORM_DEVICE)
173 #if defined(CONFIG_MALI_DT)
174 extern int mali_platform_device_init(struct platform_device *device);
175 extern int mali_platform_device_deinit(struct platform_device *device);
176 #else
177 extern int mali_platform_device_register(void);
178 extern int mali_platform_device_unregister(void);
179 #endif
180 #endif
181
182 /* Linux power management operations provided by the Mali device driver */
183 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29))
184 struct pm_ext_ops mali_dev_ext_pm_ops = {
185         .base =
186         {
187                 .suspend = mali_driver_suspend_scheduler,
188                 .resume = mali_driver_resume_scheduler,
189                 .freeze = mali_driver_suspend_scheduler,
190                 .thaw =   mali_driver_resume_scheduler,
191         },
192 };
193 #else
194 static const struct dev_pm_ops mali_dev_pm_ops = {
195 #ifdef CONFIG_PM_RUNTIME
196         .runtime_suspend = mali_driver_runtime_suspend,
197         .runtime_resume = mali_driver_runtime_resume,
198         .runtime_idle = mali_driver_runtime_idle,
199 #endif
200         .suspend = mali_driver_suspend_scheduler,
201         .resume = mali_driver_resume_scheduler,
202         .freeze = mali_driver_suspend_scheduler,
203         .thaw = mali_driver_resume_scheduler,
204         .poweroff = mali_driver_suspend_scheduler,
205 };
206 #endif
207
208 #ifdef CONFIG_MALI_DT
209 static struct of_device_id base_dt_ids[] = {
210         {.compatible = "arm,mali-300"},
211     /*-------------------------------------------------------*/
212     /* rk_ext : to use dts_for_mali_ko_befor_r5p0-01rel0. */
213         // {.compatible = "arm,mali-400"},
214         {.compatible = "arm,mali400"},
215     /*-------------------------------------------------------*/
216         {.compatible = "arm,mali-450"},
217         {.compatible = "arm,mali-470"},
218         {},
219 };
220
221 MODULE_DEVICE_TABLE(of, base_dt_ids);
222 #endif
223
224 /* The Mali device driver struct */
225 static struct platform_driver mali_platform_driver = {
226         .probe  = mali_probe,
227         .remove = mali_remove,
228 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29))
229         .pm = &mali_dev_ext_pm_ops,
230 #endif
231         .driver =
232         {
233                 .name   = MALI_GPU_NAME_UTGARD,
234                 .owner  = THIS_MODULE,
235                 .bus = &platform_bus_type,
236 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
237                 .pm = &mali_dev_pm_ops,
238 #endif
239 #ifdef CONFIG_MALI_DT
240                 .of_match_table = of_match_ptr(base_dt_ids),
241 #endif
242         },
243 };
244
245 /* Linux misc device operations (/dev/mali) */
246 struct file_operations mali_fops = {
247         .owner = THIS_MODULE,
248         .open = mali_open,
249         .release = mali_release,
250 #ifdef HAVE_UNLOCKED_IOCTL
251         .unlocked_ioctl = mali_ioctl,
252 #else
253         .ioctl = mali_ioctl,
254 #endif
255         .compat_ioctl = mali_ioctl,
256         .mmap = mali_mmap
257 };
258
259 #if MALI_ENABLE_CPU_CYCLES
260 void mali_init_cpu_time_counters(int reset, int enable_divide_by_64)
261 {
262         /* The CPU assembly reference used is: ARM Architecture Reference Manual ARMv7-AR C.b */
263         u32 write_value;
264
265         /* See B4.1.116 PMCNTENSET, Performance Monitors Count Enable Set register, VMSA */
266         /* setting p15 c9 c12 1 to 0x8000000f==CPU_CYCLE_ENABLE |EVENT_3_ENABLE|EVENT_2_ENABLE|EVENT_1_ENABLE|EVENT_0_ENABLE */
267         asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(0x8000000f));
268
269
270         /* See B4.1.117 PMCR, Performance Monitors Control Register. Writing to p15, c9, c12, 0 */
271         write_value = 1 << 0; /* Bit 0 set. Enable counters */
272         if (reset) {
273                 write_value |= 1 << 1; /* Reset event counters */
274                 write_value |= 1 << 2; /* Reset cycle counter  */
275         }
276         if (enable_divide_by_64) {
277                 write_value |= 1 << 3; /* Enable the Clock divider by 64 */
278         }
279         write_value |= 1 << 4; /* Export enable. Not needed */
280         asm volatile("MCR p15, 0, %0, c9, c12, 0\t\n" :: "r"(write_value));
281
282         /* PMOVSR Overflow Flag Status Register - Clear Clock and Event overflows */
283         asm volatile("MCR p15, 0, %0, c9, c12, 3\t\n" :: "r"(0x8000000f));
284
285
286         /* See B4.1.124 PMUSERENR - setting p15 c9 c14 to 1" */
287         /* User mode access to the Performance Monitors enabled. */
288         /* Lets User space read cpu clock cycles */
289         asm volatile("mcr p15, 0, %0, c9, c14, 0" :: "r"(1));
290 }
291
292 /** A timer function that configures the cycle clock counter on current CPU.
293  * The function \a mali_init_cpu_time_counters_on_all_cpus sets up this
294  * function to trigger on all Cpus during module load.
295  */
296 static void mali_init_cpu_clock_timer_func(unsigned long data)
297 {
298         int reset_counters, enable_divide_clock_counter_by_64;
299         int current_cpu = raw_smp_processor_id();
300         unsigned int sample0;
301         unsigned int sample1;
302
303         MALI_IGNORE(data);
304
305         reset_counters = 1;
306         enable_divide_clock_counter_by_64 = 0;
307         mali_init_cpu_time_counters(reset_counters, enable_divide_clock_counter_by_64);
308
309         sample0 = mali_get_cpu_cyclecount();
310         sample1 = mali_get_cpu_cyclecount();
311
312         MALI_DEBUG_PRINT(3, ("Init Cpu %d cycle counter- First two samples: %08x %08x \n", current_cpu, sample0, sample1));
313 }
314
315 /** A timer functions for storing current time on all cpus.
316  * Used for checking if the clocks have similar values or if they are drifting.
317  */
318 static void mali_print_cpu_clock_timer_func(unsigned long data)
319 {
320         int current_cpu = raw_smp_processor_id();
321         unsigned int sample0;
322
323         MALI_IGNORE(data);
324         sample0 = mali_get_cpu_cyclecount();
325         if (current_cpu < 8) {
326                 mali_cpu_clock_last_value[current_cpu] = sample0;
327         }
328 }
329
330 /** Init the performance registers on all CPUs to count clock cycles.
331  * For init \a print_only should be 0.
332  * If \a print_only is 1, it will intead print the current clock value of all CPUs.
333  */
334 void mali_init_cpu_time_counters_on_all_cpus(int print_only)
335 {
336         int i = 0;
337         int cpu_number;
338         int jiffies_trigger;
339         int jiffies_wait;
340
341         jiffies_wait = 2;
342         jiffies_trigger = jiffies + jiffies_wait;
343
344         for (i = 0 ; i < 8 ; i++) {
345                 init_timer(&mali_init_cpu_clock_timers[i]);
346                 if (print_only) mali_init_cpu_clock_timers[i].function = mali_print_cpu_clock_timer_func;
347                 else            mali_init_cpu_clock_timers[i].function = mali_init_cpu_clock_timer_func;
348                 mali_init_cpu_clock_timers[i].expires = jiffies_trigger ;
349         }
350         cpu_number = cpumask_first(cpu_online_mask);
351         for (i = 0 ; i < 8 ; i++) {
352                 int next_cpu;
353                 add_timer_on(&mali_init_cpu_clock_timers[i], cpu_number);
354                 next_cpu = cpumask_next(cpu_number, cpu_online_mask);
355                 if (next_cpu >= nr_cpu_ids) break;
356                 cpu_number = next_cpu;
357         }
358
359         while (jiffies_wait) jiffies_wait = schedule_timeout_uninterruptible(jiffies_wait);
360
361         for (i = 0 ; i < 8 ; i++) {
362                 del_timer_sync(&mali_init_cpu_clock_timers[i]);
363         }
364
365         if (print_only) {
366                 if ((0 == mali_cpu_clock_last_value[2]) && (0 == mali_cpu_clock_last_value[3])) {
367                         /* Diff can be printed if we want to check if the clocks are in sync
368                         int diff = mali_cpu_clock_last_value[0] - mali_cpu_clock_last_value[1];*/
369                         MALI_DEBUG_PRINT(2, ("CPU cycle counters readout all: %08x %08x\n", mali_cpu_clock_last_value[0], mali_cpu_clock_last_value[1]));
370                 } else {
371                         MALI_DEBUG_PRINT(2, ("CPU cycle counters readout all: %08x %08x %08x %08x\n", mali_cpu_clock_last_value[0], mali_cpu_clock_last_value[1], mali_cpu_clock_last_value[2], mali_cpu_clock_last_value[3]));
372                 }
373         }
374 }
375 #endif
376
377 int mali_module_init(void)
378 {
379         int err = 0;
380
381         MALI_DEBUG_PRINT(2, ("Inserting Mali v%d device driver. \n", _MALI_API_VERSION));
382         MALI_DEBUG_PRINT(2, ("Compiled: %s, time: %s.\n", __DATE__, __TIME__));
383         MALI_DEBUG_PRINT(2, ("Driver revision: %s\n", SVN_REV_STRING));
384     
385         I("svn_rev_string_from_arm of this mali_ko is '%s', rk_ko_ver is '%d', built at '%s', on '%s'.",
386                 SVN_REV_STRING,
387                 RK_KO_VER,
388                 __TIME__,
389                 __DATE__);
390
391 #if MALI_ENABLE_CPU_CYCLES
392         mali_init_cpu_time_counters_on_all_cpus(0);
393         MALI_DEBUG_PRINT(2, ("CPU cycle counter setup complete\n"));
394         /* Printing the current cpu counters */
395         mali_init_cpu_time_counters_on_all_cpus(1);
396 #endif
397
398         /* Initialize module wide settings */
399 #ifdef MALI_FAKE_PLATFORM_DEVICE
400 #ifndef CONFIG_MALI_DT
401         MALI_DEBUG_PRINT(2, ("mali_module_init() registering device\n"));
402         err = mali_platform_device_register();
403         if (0 != err) {
404                 return err;
405         }
406 #endif
407 #endif
408
409         MALI_DEBUG_PRINT(2, ("mali_module_init() registering driver\n"));
410
411         err = platform_driver_register(&mali_platform_driver);
412
413         if (0 != err) {
414                 MALI_DEBUG_PRINT(2, ("mali_module_init() Failed to register driver (%d)\n", err));
415 #ifdef MALI_FAKE_PLATFORM_DEVICE
416 #ifndef CONFIG_MALI_DT
417                 mali_platform_device_unregister();
418 #endif
419 #endif
420                 mali_platform_device = NULL;
421                 return err;
422         }
423
424 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
425         err = _mali_internal_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
426         if (0 != err) {
427                 /* No biggie if we wheren't able to initialize the profiling */
428                 MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
429         }
430 #endif
431
432         /* Tracing the current frequency and voltage from boot/insmod*/
433 #if defined(CONFIG_MALI400_PROFILING) && defined(CONFIG_MALI_DVFS)
434         /* Just call mali_get_current_gpu_clk_item(),to record current clk info.*/
435         mali_get_current_gpu_clk_item(&mali_gpu_clk[0]);
436         _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
437                                       MALI_PROFILING_EVENT_CHANNEL_GPU |
438                                       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
439                                       mali_gpu_clk[0].clock,
440                                       mali_gpu_clk[0].vol / 1000,
441                                       0, 0, 0);
442 #endif
443
444         MALI_PRINT(("Mali device driver loaded\n"));
445
446         return 0; /* Success */
447 }
448
449 void mali_module_exit(void)
450 {
451         MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n", _MALI_API_VERSION));
452
453         MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering driver\n"));
454
455         platform_driver_unregister(&mali_platform_driver);
456
457 #if defined(MALI_FAKE_PLATFORM_DEVICE)
458 #ifndef CONFIG_MALI_DT
459         MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering device\n"));
460         mali_platform_device_unregister();
461 #endif
462 #endif
463
464         /* Tracing the current frequency and voltage from rmmod*/
465         _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
466                                       MALI_PROFILING_EVENT_CHANNEL_GPU |
467                                       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
468                                       0,
469                                       0,
470                                       0, 0, 0);
471
472 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
473         _mali_internal_profiling_term();
474 #endif
475
476         MALI_PRINT(("Mali device driver unloaded\n"));
477 }
478
479 static int mali_probe(struct platform_device *pdev)
480 {
481         int err;
482
483         MALI_DEBUG_PRINT(2, ("mali_probe(): Called for platform device %s\n", pdev->name));
484
485         if (NULL != mali_platform_device) {
486                 /* Already connected to a device, return error */
487                 MALI_PRINT_ERROR(("mali_probe(): The Mali driver is already connected with a Mali device."));
488                 return -EEXIST;
489         }
490
491         mali_platform_device = pdev;
492
493         dev_info(&pdev->dev, "mali_platform_device->num_resources = %d\n",
494                 mali_platform_device->num_resources);
495         
496         {
497                 int i = 0;
498
499                 for(i = 0; i < mali_platform_device->num_resources; i++)
500                         dev_info(&pdev->dev,
501                                  "resource[%d].start = 0x%pa\n",
502                                  i,
503                                  &mali_platform_device->resource[i].start);
504         }
505
506 #ifdef CONFIG_MALI_DT
507         /* If we use DT to initialize our DDK, we have to prepare somethings. */
508         err = mali_platform_device_init(mali_platform_device);
509         if (0 != err) {
510                 MALI_PRINT_ERROR(("mali_probe(): Failed to initialize platform device."));
511                 return -EFAULT;
512         }
513 #endif
514
515         if (_MALI_OSK_ERR_OK == _mali_osk_wq_init()) {
516                 /* Initialize the Mali GPU HW specified by pdev */
517                 if (_MALI_OSK_ERR_OK == mali_initialize_subsystems()) {
518                         /* Register a misc device (so we are accessible from user space) */
519                         err = mali_miscdevice_register(pdev);
520                         if (0 == err) {
521                                 /* Setup sysfs entries */
522                                 err = mali_sysfs_register(mali_dev_name);
523
524                                 if (0 == err) {
525                                         MALI_DEBUG_PRINT(2, ("mali_probe(): Successfully initialized driver for platform device %s\n", pdev->name));
526
527                                         return 0;
528                                 } else {
529                                         MALI_PRINT_ERROR(("mali_probe(): failed to register sysfs entries"));
530                                 }
531                                 mali_miscdevice_unregister();
532                         } else {
533                                 MALI_PRINT_ERROR(("mali_probe(): failed to register Mali misc device."));
534                         }
535                         mali_terminate_subsystems();
536                 } else {
537                         MALI_PRINT_ERROR(("mali_probe(): Failed to initialize Mali device driver."));
538                 }
539                 _mali_osk_wq_term();
540         }
541
542         mali_platform_device = NULL;
543         return -EFAULT;
544 }
545
546 static int mali_remove(struct platform_device *pdev)
547 {
548         MALI_DEBUG_PRINT(2, ("mali_remove() called for platform device %s\n", pdev->name));
549         mali_sysfs_unregister();
550         mali_miscdevice_unregister();
551         mali_terminate_subsystems();
552         _mali_osk_wq_term();
553 #ifdef CONFIG_MALI_DT
554         mali_platform_device_deinit(mali_platform_device);
555 #endif
556         mali_platform_device = NULL;
557         return 0;
558 }
559
560 static int mali_miscdevice_register(struct platform_device *pdev)
561 {
562         int err;
563
564         mali_miscdevice.minor = MISC_DYNAMIC_MINOR;
565         mali_miscdevice.name = mali_dev_name;
566         mali_miscdevice.fops = &mali_fops;
567         mali_miscdevice.parent = get_device(&pdev->dev);
568
569         err = misc_register(&mali_miscdevice);
570         if (0 != err) {
571                 MALI_PRINT_ERROR(("Failed to register misc device, misc_register() returned %d\n", err));
572         }
573
574         return err;
575 }
576
577 static void mali_miscdevice_unregister(void)
578 {
579         misc_deregister(&mali_miscdevice);
580 }
581
582 static int mali_driver_suspend_scheduler(struct device *dev)
583 {
584         mali_pm_os_suspend(MALI_TRUE);
585         /* Tracing the frequency and voltage after mali is suspended */
586         _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
587                                       MALI_PROFILING_EVENT_CHANNEL_GPU |
588                                       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
589                                       0,
590                                       0,
591                                       0, 0, 0);
592         return 0;
593 }
594
595 static int mali_driver_resume_scheduler(struct device *dev)
596 {
597         /* Tracing the frequency and voltage after mali is resumed */
598 #if defined(CONFIG_MALI400_PROFILING) && defined(CONFIG_MALI_DVFS)
599         /* Just call mali_get_current_gpu_clk_item() once,to record current clk info.*/
600         if (is_first_resume == 1) {
601                 mali_get_current_gpu_clk_item(&mali_gpu_clk[1]);
602                 is_first_resume = 0;
603         }
604         _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
605                                       MALI_PROFILING_EVENT_CHANNEL_GPU |
606                                       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
607                                       mali_gpu_clk[1].clock,
608                                       mali_gpu_clk[1].vol / 1000,
609                                       0, 0, 0);
610 #endif
611         mali_pm_os_resume();
612         return 0;
613 }
614
615 #ifdef CONFIG_PM_RUNTIME
616 static int mali_driver_runtime_suspend(struct device *dev)
617 {
618         if (MALI_TRUE == mali_pm_runtime_suspend()) {
619                 /* Tracing the frequency and voltage after mali is suspended */
620                 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
621                                               MALI_PROFILING_EVENT_CHANNEL_GPU |
622                                               MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
623                                               0,
624                                               0,
625                                               0, 0, 0);
626
627                 return 0;
628         } else {
629                 return -EBUSY;
630         }
631 }
632
633 static int mali_driver_runtime_resume(struct device *dev)
634 {
635         /* Tracing the frequency and voltage after mali is resumed */
636 #if defined(CONFIG_MALI400_PROFILING) && defined(CONFIG_MALI_DVFS)
637         /* Just call mali_get_current_gpu_clk_item() once,to record current clk info.*/
638         if (is_first_resume == 1) {
639                 mali_get_current_gpu_clk_item(&mali_gpu_clk[1]);
640                 is_first_resume = 0;
641         }
642         _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
643                                       MALI_PROFILING_EVENT_CHANNEL_GPU |
644                                       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
645                                       mali_gpu_clk[1].clock,
646                                       mali_gpu_clk[1].vol / 1000,
647                                       0, 0, 0);
648 #endif
649
650         mali_pm_runtime_resume();
651         return 0;
652 }
653
654 static int mali_driver_runtime_idle(struct device *dev)
655 {
656         /* Nothing to do */
657         return 0;
658 }
659 #endif
660
661 static int mali_open(struct inode *inode, struct file *filp)
662 {
663         struct mali_session_data *session_data;
664         _mali_osk_errcode_t err;
665
666         /* input validation */
667         if (mali_miscdevice.minor != iminor(inode)) {
668                 MALI_PRINT_ERROR(("mali_open() Minor does not match\n"));
669                 return -ENODEV;
670         }
671
672         /* allocated struct to track this session */
673         err = _mali_ukk_open((void **)&session_data);
674         if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
675
676         /* initialize file pointer */
677         filp->f_pos = 0;
678
679         /* link in our session data */
680         filp->private_data = (void *)session_data;
681
682         filp->f_mapping = mali_mem_swap_get_global_swap_file()->f_mapping;
683
684         return 0;
685 }
686
687 static int mali_release(struct inode *inode, struct file *filp)
688 {
689         _mali_osk_errcode_t err;
690
691         /* input validation */
692         if (mali_miscdevice.minor != iminor(inode)) {
693                 MALI_PRINT_ERROR(("mali_release() Minor does not match\n"));
694                 return -ENODEV;
695         }
696
697         err = _mali_ukk_close((void **)&filp->private_data);
698         if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
699
700         return 0;
701 }
702
703 int map_errcode(_mali_osk_errcode_t err)
704 {
705         switch (err) {
706         case _MALI_OSK_ERR_OK :
707                 return 0;
708         case _MALI_OSK_ERR_FAULT:
709                 return -EFAULT;
710         case _MALI_OSK_ERR_INVALID_FUNC:
711                 return -ENOTTY;
712         case _MALI_OSK_ERR_INVALID_ARGS:
713                 return -EINVAL;
714         case _MALI_OSK_ERR_NOMEM:
715                 return -ENOMEM;
716         case _MALI_OSK_ERR_TIMEOUT:
717                 return -ETIMEDOUT;
718         case _MALI_OSK_ERR_RESTARTSYSCALL:
719                 return -ERESTARTSYS;
720         case _MALI_OSK_ERR_ITEM_NOT_FOUND:
721                 return -ENOENT;
722         default:
723                 return -EFAULT;
724         }
725 }
726
727 #ifdef HAVE_UNLOCKED_IOCTL
728 static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
729 #else
730 static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
731 #endif
732 {
733         int err;
734         struct mali_session_data *session_data;
735
736 #ifndef HAVE_UNLOCKED_IOCTL
737         /* inode not used */
738         (void)inode;
739 #endif
740
741         MALI_DEBUG_PRINT(7, ("Ioctl received 0x%08X 0x%08lX\n", cmd, arg));
742
743         session_data = (struct mali_session_data *)filp->private_data;
744         if (NULL == session_data) {
745                 MALI_DEBUG_PRINT(7, ("filp->private_data was NULL\n"));
746                 return -ENOTTY;
747         }
748
749         if (NULL == (void *)arg) {
750                 MALI_DEBUG_PRINT(7, ("arg was NULL\n"));
751                 return -ENOTTY;
752         }
753
754         switch (cmd) {
755         case MALI_IOC_WAIT_FOR_NOTIFICATION:
756                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_wait_for_notification_s), sizeof(u64)));
757                 err = wait_for_notification_wrapper(session_data, (_mali_uk_wait_for_notification_s __user *)arg);
758                 break;
759
760         case MALI_IOC_GET_API_VERSION_V2:
761                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_api_version_v2_s), sizeof(u64)));
762                 err = get_api_version_v2_wrapper(session_data, (_mali_uk_get_api_version_v2_s __user *)arg);
763                 break;
764
765         case MALI_IOC_GET_API_VERSION:
766                 err = get_api_version_wrapper(session_data, (_mali_uk_get_api_version_s __user *)arg);
767                 break;
768
769         case MALI_IOC_POST_NOTIFICATION:
770                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_post_notification_s), sizeof(u64)));
771                 err = post_notification_wrapper(session_data, (_mali_uk_post_notification_s __user *)arg);
772                 break;
773
774     /* rk_ext : 从对 r5p0-01rel0 集成开始, 不再使用. */
775 #if 0
776         case MALI_IOC_GET_MALI_VERSION_IN_RK30:
777                 err = get_mali_version_in_rk30_wrapper(session_data, (_mali_uk_get_mali_version_in_rk30_s __user *)arg);
778                 break;
779 #else
780     case MALI_IOC_GET_RK_KO_VERSION:
781                 err = get_rk_ko_version_wrapper(session_data, (_mali_rk_ko_version_s __user *)arg);
782                 break;
783 #endif
784         
785         case MALI_IOC_GET_USER_SETTINGS:
786                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_user_settings_s), sizeof(u64)));
787                 err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg);
788                 break;
789
790         case MALI_IOC_REQUEST_HIGH_PRIORITY:
791                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_request_high_priority_s), sizeof(u64)));
792                 err = request_high_priority_wrapper(session_data, (_mali_uk_request_high_priority_s __user *)arg);
793                 break;
794
795         case MALI_IOC_PENDING_SUBMIT:
796                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_pending_submit_s), sizeof(u64)));
797                 err = pending_submit_wrapper(session_data, (_mali_uk_pending_submit_s __user *)arg);
798                 break;
799
800 #if defined(CONFIG_MALI400_PROFILING)
801         case MALI_IOC_PROFILING_ADD_EVENT:
802                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_profiling_add_event_s), sizeof(u64)));
803                 err = profiling_add_event_wrapper(session_data, (_mali_uk_profiling_add_event_s __user *)arg);
804                 break;
805
806         case MALI_IOC_PROFILING_REPORT_SW_COUNTERS:
807                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_sw_counters_report_s), sizeof(u64)));
808                 err = profiling_report_sw_counters_wrapper(session_data, (_mali_uk_sw_counters_report_s __user *)arg);
809                 break;
810
811         case MALI_IOC_PROFILING_STREAM_FD_GET:
812                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_profiling_stream_fd_get_s), sizeof(u64)));
813                 err = profiling_get_stream_fd_wrapper(session_data, (_mali_uk_profiling_stream_fd_get_s __user *)arg);
814                 break;
815
816         case MALI_IOC_PROILING_CONTROL_SET:
817                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_profiling_control_set_s), sizeof(u64)));
818                 err = profiling_control_set_wrapper(session_data, (_mali_uk_profiling_control_set_s __user *)arg);
819                 break;
820 #else
821
822         case MALI_IOC_PROFILING_ADD_EVENT:          /* FALL-THROUGH */
823         case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: /* FALL-THROUGH */
824                 MALI_DEBUG_PRINT(2, ("Profiling not supported\n"));
825                 err = -ENOTTY;
826                 break;
827 #endif
828
829         case MALI_IOC_PROFILING_MEMORY_USAGE_GET:
830                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_profiling_memory_usage_get_s), sizeof(u64)));
831                 err = mem_usage_get_wrapper(session_data, (_mali_uk_profiling_memory_usage_get_s __user *)arg);
832                 break;
833
834         case MALI_IOC_MEM_ALLOC:
835                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_alloc_mem_s), sizeof(u64)));
836                 err = mem_alloc_wrapper(session_data, (_mali_uk_alloc_mem_s __user *)arg);
837                 break;
838
839         case MALI_IOC_MEM_FREE:
840                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_free_mem_s), sizeof(u64)));
841                 err = mem_free_wrapper(session_data, (_mali_uk_free_mem_s __user *)arg);
842                 break;
843
844         case MALI_IOC_MEM_BIND:
845                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_bind_mem_s), sizeof(u64)));
846                 err = mem_bind_wrapper(session_data, (_mali_uk_bind_mem_s __user *)arg);
847                 break;
848
849         case MALI_IOC_MEM_UNBIND:
850                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_unbind_mem_s), sizeof(u64)));
851                 err = mem_unbind_wrapper(session_data, (_mali_uk_unbind_mem_s __user *)arg);
852                 break;
853
854         case MALI_IOC_MEM_COW:
855                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_cow_mem_s), sizeof(u64)));
856                 err = mem_cow_wrapper(session_data, (_mali_uk_cow_mem_s __user *)arg);
857                 break;
858
859         case MALI_IOC_MEM_COW_MODIFY_RANGE:
860                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_cow_modify_range_s), sizeof(u64)));
861                 err = mem_cow_modify_range_wrapper(session_data, (_mali_uk_cow_modify_range_s __user *)arg);
862                 break;
863
864         case MALI_IOC_MEM_RESIZE:
865                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_mem_resize_s), sizeof(u64)));
866                 err = mem_resize_mem_wrapper(session_data, (_mali_uk_mem_resize_s __user *)arg);
867                 break;
868
869         case MALI_IOC_MEM_WRITE_SAFE:
870                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_mem_write_safe_s), sizeof(u64)));
871                 err = mem_write_safe_wrapper(session_data, (_mali_uk_mem_write_safe_s __user *)arg);
872                 break;
873
874         case MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE:
875                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_query_mmu_page_table_dump_size_s), sizeof(u64)));
876                 err = mem_query_mmu_page_table_dump_size_wrapper(session_data, (_mali_uk_query_mmu_page_table_dump_size_s __user *)arg);
877                 break;
878
879         case MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE:
880                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_dump_mmu_page_table_s), sizeof(u64)));
881                 err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg);
882                 break;
883
884         case MALI_IOC_MEM_DMA_BUF_GET_SIZE:
885 #ifdef CONFIG_DMA_SHARED_BUFFER
886                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_dma_buf_get_size_s), sizeof(u64)));
887                 err = mali_dma_buf_get_size(session_data, (_mali_uk_dma_buf_get_size_s __user *)arg);
888 #else
889                 MALI_DEBUG_PRINT(2, ("DMA-BUF not supported\n"));
890                 err = -ENOTTY;
891 #endif
892                 break;
893
894         case MALI_IOC_PP_START_JOB:
895                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_pp_start_job_s), sizeof(u64)));
896                 err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg);
897                 break;
898
899         case MALI_IOC_PP_AND_GP_START_JOB:
900                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_pp_and_gp_start_job_s), sizeof(u64)));
901                 err = pp_and_gp_start_job_wrapper(session_data, (_mali_uk_pp_and_gp_start_job_s __user *)arg);
902                 break;
903
904         case MALI_IOC_PP_NUMBER_OF_CORES_GET:
905                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_pp_number_of_cores_s), sizeof(u64)));
906                 err = pp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_pp_number_of_cores_s __user *)arg);
907                 break;
908
909         case MALI_IOC_PP_CORE_VERSION_GET:
910                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_pp_core_version_s), sizeof(u64)));
911                 err = pp_get_core_version_wrapper(session_data, (_mali_uk_get_pp_core_version_s __user *)arg);
912                 break;
913
914         case MALI_IOC_PP_DISABLE_WB:
915                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_pp_disable_wb_s), sizeof(u64)));
916                 err = pp_disable_wb_wrapper(session_data, (_mali_uk_pp_disable_wb_s __user *)arg);
917                 break;
918
919         case MALI_IOC_GP2_START_JOB:
920                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_gp_start_job_s), sizeof(u64)));
921                 err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg);
922                 break;
923
924         case MALI_IOC_GP2_NUMBER_OF_CORES_GET:
925                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_gp_number_of_cores_s), sizeof(u64)));
926                 err = gp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_gp_number_of_cores_s __user *)arg);
927                 break;
928
929         case MALI_IOC_GP2_CORE_VERSION_GET:
930                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_get_gp_core_version_s), sizeof(u64)));
931                 err = gp_get_core_version_wrapper(session_data, (_mali_uk_get_gp_core_version_s __user *)arg);
932                 break;
933
934         case MALI_IOC_GP2_SUSPEND_RESPONSE:
935                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_gp_suspend_response_s), sizeof(u64)));
936                 err = gp_suspend_response_wrapper(session_data, (_mali_uk_gp_suspend_response_s __user *)arg);
937                 break;
938
939         case MALI_IOC_VSYNC_EVENT_REPORT:
940                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_vsync_event_report_s), sizeof(u64)));
941                 err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg);
942                 break;
943
944         case MALI_IOC_TIMELINE_GET_LATEST_POINT:
945                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_timeline_get_latest_point_s), sizeof(u64)));
946                 err = timeline_get_latest_point_wrapper(session_data, (_mali_uk_timeline_get_latest_point_s __user *)arg);
947                 break;
948         case MALI_IOC_TIMELINE_WAIT:
949                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_timeline_wait_s), sizeof(u64)));
950                 err = timeline_wait_wrapper(session_data, (_mali_uk_timeline_wait_s __user *)arg);
951                 break;
952         case MALI_IOC_TIMELINE_CREATE_SYNC_FENCE:
953                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_timeline_create_sync_fence_s), sizeof(u64)));
954                 err = timeline_create_sync_fence_wrapper(session_data, (_mali_uk_timeline_create_sync_fence_s __user *)arg);
955                 break;
956         case MALI_IOC_SOFT_JOB_START:
957                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_soft_job_start_s), sizeof(u64)));
958                 err = soft_job_start_wrapper(session_data, (_mali_uk_soft_job_start_s __user *)arg);
959                 break;
960         case MALI_IOC_SOFT_JOB_SIGNAL:
961                 BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_soft_job_signal_s), sizeof(u64)));
962                 err = soft_job_signal_wrapper(session_data, (_mali_uk_soft_job_signal_s __user *)arg);
963                 break;
964
965         default:
966                 MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg));
967                 err = -ENOTTY;
968         };
969
970         return err;
971 }
972
973 late_initcall_sync(mali_module_init);
974 module_exit(mali_module_exit);
975
976 MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE);
977 MODULE_AUTHOR("ARM Ltd.");
978 MODULE_VERSION(SVN_REV_STRING);