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