tizen 2.4 release
[kernel/linux-3.0.git] / drivers / gpu / arm / mali400 / r4p0_rel0 / platform / pegasus-m400 / exynos4.c
1 /* drivers/gpu/mali400/mali/platform/pegasus-m400/exynos4.c
2  *
3  * Copyright 2011 by S.LSI. Samsung Electronics Inc.
4  * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea
5  *
6  * Samsung SoC Mali400 DVFS driver
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software FoundatIon.
11  */
12
13 /**
14  * @file exynos4.c
15  * Platform specific Mali driver functions for the exynos 4XXX based platforms
16  */
17 #include <linux/platform_device.h>
18 #include <linux/version.h>
19 #include <linux/pm.h>
20 #include <linux/suspend.h>
21 #include <linux/dma-mapping.h>
22
23 #ifdef CONFIG_PM_RUNTIME
24 #include <linux/pm_runtime.h>
25 #endif
26
27 #ifdef CONFIG_MALI_DVFS
28 #include "mali_kernel_utilization.h"
29 #endif /* CONFIG_MALI_DVFS */
30
31 #include <linux/mali/mali_utgard.h>
32 #include "mali_kernel_common.h"
33 #include "mali_kernel_linux.h"
34 #include "mali_pm.h"
35
36 #include <plat/pd.h>
37
38 #include "exynos4_pmm.h"
39
40 #if defined(CONFIG_PM_RUNTIME)
41 /* We does not need PM NOTIFIER in r3p2 DDK */
42 //#define USE_PM_NOTIFIER
43 #endif
44
45 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
46 struct exynos_pm_domain;
47 extern struct exynos_pm_domain exynos4_pd_g3d;
48 void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, struct exynos_pm_domain *pd);
49 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
50 extern struct platform_device exynos4_device_pd[];
51 #else
52 extern struct platform_device s5pv310_device_pd[];
53 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) */
54
55 static void mali_platform_device_release(struct device *device);
56
57 #if defined(CONFIG_PM_RUNTIME)
58 #if defined(USE_PM_NOTIFIER)
59 static int mali_os_suspend(struct device *device);
60 static int mali_os_resume(struct device *device);
61 static int mali_os_freeze(struct device *device);
62 static int mali_os_thaw(struct device *device);
63
64 static int mali_runtime_suspend(struct device *device);
65 static int mali_runtime_resume(struct device *device);
66 static int mali_runtime_idle(struct device *device);
67 #endif
68 #endif
69
70 #if defined(CONFIG_ARCH_S5PV310) && !defined(CONFIG_BOARD_HKDKC210)
71
72 /* This is for other SMDK boards */
73 #define MALI_BASE_IRQ 232
74
75 #else
76
77 /* This is for the Odroid boards */
78 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
79 #define MALI_BASE_IRQ 182
80 #else
81 #define MALI_BASE_IRQ 150
82 #endif
83
84 #endif
85
86 #define MALI_GP_IRQ        MALI_BASE_IRQ + 9
87 #define MALI_PP0_IRQ      MALI_BASE_IRQ + 5
88 #define MALI_PP1_IRQ      MALI_BASE_IRQ + 6
89 #define MALI_PP2_IRQ      MALI_BASE_IRQ + 7
90 #define MALI_PP3_IRQ      MALI_BASE_IRQ + 8
91 #define MALI_GP_MMU_IRQ   MALI_BASE_IRQ + 4
92 #define MALI_PP0_MMU_IRQ  MALI_BASE_IRQ + 0
93 #define MALI_PP1_MMU_IRQ  MALI_BASE_IRQ + 1
94 #define MALI_PP2_MMU_IRQ  MALI_BASE_IRQ + 2
95 #define MALI_PP3_MMU_IRQ  MALI_BASE_IRQ + 3
96
97 static struct resource mali_gpu_resources[] =
98 {
99         MALI_GPU_RESOURCES_MALI400_MP4(0x13000000,
100                                                                    MALI_GP_IRQ, MALI_GP_MMU_IRQ,
101                                                                    MALI_PP0_IRQ, MALI_PP0_MMU_IRQ,
102                                                                    MALI_PP1_IRQ, MALI_PP1_MMU_IRQ,
103                                                                    MALI_PP2_IRQ, MALI_PP2_MMU_IRQ,
104                                                                    MALI_PP3_IRQ, MALI_PP3_MMU_IRQ)
105 };
106
107 #ifdef CONFIG_PM_RUNTIME
108 #if defined(USE_PM_NOTIFIER)
109 static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy);
110
111 static struct notifier_block mali_pwr_notif_block = {
112         .notifier_call = mali_pwr_suspend_notifier
113 };
114 #endif
115 #endif /* CONFIG_PM_RUNTIME */
116
117 #if 0
118 static struct dev_pm_ops mali_gpu_device_type_pm_ops =
119 {
120 #ifndef CONFIG_PM_RUNTIME
121         .suspend = mali_os_suspend,
122         .resume = mali_os_resume,
123 #endif
124         .freeze = mali_os_freeze,
125         .thaw = mali_os_thaw,
126 #ifdef CONFIG_PM_RUNTIME
127         .runtime_suspend = mali_runtime_suspend,
128         .runtime_resume = mali_runtime_resume,
129         .runtime_idle = mali_runtime_idle,
130 #endif
131 };
132 #endif
133
134 #if defined(USE_PM_NOTIFIER)
135 static struct device_type mali_gpu_device_device_type =
136 {
137         .pm = &mali_gpu_device_type_pm_ops,
138 };
139 #endif
140
141 static struct platform_device mali_gpu_device =
142 {
143         .name = "mali_dev", /* MALI_SEC MALI_GPU_NAME_UTGARD, */
144         .id = 0,
145 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
146         /* Set in mali_platform_device_register() for these kernels */
147 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
148         .dev.parent = &exynos4_device_pd[PD_G3D].dev,
149 #else
150         .dev.parent = &s5pv310_device_pd[PD_G3D].dev,
151 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) */
152         .dev.release = mali_platform_device_release,
153 #if 0
154         /*
155          * We temporarily make use of a device type so that we can control the Mali power
156          * from within the mali.ko (since the default platform bus implementation will not do that).
157          * Ideally .dev.pm_domain should be used instead, as this is the new framework designed
158          * to control the power of devices.
159          */
160         .dev.type = &mali_gpu_device_device_type, /* We should probably use the pm_domain instead of type on newer kernels */
161 #endif
162         .dev.coherent_dma_mask = DMA_BIT_MASK(32),
163 };
164
165 static struct mali_gpu_device_data mali_gpu_data =
166 {
167         .shared_mem_size = 256 * 1024 * 1024, /* 256MB */
168         .fb_start = 0x40000000,
169         .fb_size = 0xb1000000,
170         .utilization_interval = 100, /* 100ms */
171         .utilization_callback = mali_gpu_utilization_handler,
172 };
173
174 int mali_platform_device_register(void)
175 {
176         int err;
177
178         MALI_DEBUG_PRINT(4, ("mali_platform_device_register() called\n"));
179
180 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
181         exynos_pm_add_dev_to_genpd(&mali_gpu_device, &exynos4_pd_g3d);
182 #endif
183
184         /* Connect resources to the device */
185         err = platform_device_add_resources(&mali_gpu_device, mali_gpu_resources, sizeof(mali_gpu_resources) / sizeof(mali_gpu_resources[0]));
186         if (0 == err)
187         {
188                 err = platform_device_add_data(&mali_gpu_device, &mali_gpu_data, sizeof(mali_gpu_data));
189                 if (0 == err)
190                 {
191 #ifdef CONFIG_PM_RUNTIME
192 #if defined(USE_PM_NOTIFIER)
193                         err = register_pm_notifier(&mali_pwr_notif_block);
194                         if (err)
195                         {
196                                 goto plat_init_err;
197                         }
198 #endif
199 #endif /* CONFIG_PM_RUNTIME */
200
201                         /* Register the platform device */
202                         err = platform_device_register(&mali_gpu_device);
203                         if (0 == err)
204                         {
205                                 mali_platform_init(&(mali_gpu_device.dev));
206
207 #ifdef CONFIG_PM_RUNTIME
208 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
209                                 pm_runtime_set_autosuspend_delay(&(mali_gpu_device.dev), 1000);
210                                 pm_runtime_use_autosuspend(&(mali_gpu_device.dev));
211 #endif
212                                 pm_runtime_enable(&(mali_gpu_device.dev));
213 #endif
214
215                                 return 0;
216                         }
217                 }
218
219 #ifdef CONFIG_PM_RUNTIME
220 #if defined(USE_PM_NOTIFIER)
221 plat_init_err:
222                 unregister_pm_notifier(&mali_pwr_notif_block);
223 #endif
224 #endif /* CONFIG_PM_RUNTIME */
225                 platform_device_unregister(&mali_gpu_device);
226         }
227
228         return err;
229 }
230
231 void mali_platform_device_unregister(void)
232 {
233         MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
234
235 #ifdef CONFIG_PM_RUNTIME
236 #if defined(USE_PM_NOTIFIER)
237         unregister_pm_notifier(&mali_pwr_notif_block);
238 #endif
239 #endif /* CONFIG_PM_RUNTIME */
240
241         mali_platform_deinit(&(mali_gpu_device.dev));
242
243         platform_device_unregister(&mali_gpu_device);
244 }
245
246 static void mali_platform_device_release(struct device *device)
247 {
248         MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
249 }
250
251 #ifdef CONFIG_PM_RUNTIME
252 #if defined(USE_PM_NOTIFIER)
253 static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy)
254 {
255         int err = 0;
256         switch (event)
257         {
258                 case PM_SUSPEND_PREPARE:
259                         mali_pm_os_suspend();
260                         err = mali_os_suspend(&(mali_platform_device->dev));
261                         break;
262
263                 case PM_POST_SUSPEND:
264                         err = mali_os_resume(&(mali_platform_device->dev));
265                         mali_pm_os_resume();
266                         break;
267                 default:
268                         break;
269         }
270         return err;
271 }
272
273 static int mali_os_suspend(struct device *device)
274 {
275         int ret = 0;
276         MALI_DEBUG_PRINT(4, ("mali_os_suspend() called\n"));
277
278 #ifdef CONFIG_MALI_DVFS
279         mali_utilization_suspend();
280 #endif
281
282         if (NULL != device &&
283                 NULL != device->driver &&
284                 NULL != device->driver->pm &&
285                 NULL != device->driver->pm->suspend)
286         {
287                 /* Need to notify Mali driver about this event */
288                 ret = device->driver->pm->suspend(device);
289         }
290
291         mali_platform_power_mode_change(device, MALI_POWER_MODE_DEEP_SLEEP);
292
293         return ret;
294 }
295
296 static int mali_os_resume(struct device *device)
297 {
298         int ret = 0;
299
300         MALI_DEBUG_PRINT(4, ("mali_os_resume() called\n"));
301 #ifdef CONFIG_REGULATOR
302         mali_regulator_enable();
303         g3d_power_domain_control(1);
304 #endif
305         mali_platform_power_mode_change(device, MALI_POWER_MODE_ON);
306
307         if (NULL != device &&
308                 NULL != device->driver &&
309                 NULL != device->driver->pm &&
310                 NULL != device->driver->pm->resume)
311         {
312                 /* Need to notify Mali driver about this event */
313                 ret = device->driver->pm->resume(device);
314         }
315
316         return ret;
317 }
318
319 static int mali_os_freeze(struct device *device)
320 {
321         int ret = 0;
322         MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
323
324         if (NULL != device->driver &&
325                 NULL != device->driver->pm &&
326                 NULL != device->driver->pm->freeze)
327         {
328                 /* Need to notify Mali driver about this event */
329                 ret = device->driver->pm->freeze(device);
330         }
331
332         return ret;
333 }
334
335 static int mali_os_thaw(struct device *device)
336 {
337         int ret = 0;
338         MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
339
340         if (NULL != device->driver &&
341                 NULL != device->driver->pm &&
342                 NULL != device->driver->pm->thaw)
343         {
344                 /* Need to notify Mali driver about this event */
345                 ret = device->driver->pm->thaw(device);
346         }
347
348         return ret;
349 }
350
351 static int mali_runtime_suspend(struct device *device)
352 {
353         int ret = 0;
354
355         MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
356         if (NULL != device->driver &&
357                 NULL != device->driver->pm &&
358                 NULL != device->driver->pm->runtime_suspend)
359         {
360                 /* Need to notify Mali driver about this event */
361                 ret = device->driver->pm->runtime_suspend(device);
362         }
363
364         mali_platform_power_mode_change(device, MALI_POWER_MODE_LIGHT_SLEEP);
365
366         return ret;
367 }
368
369 static int mali_runtime_resume(struct device *device)
370 {
371         int ret = 0;
372         MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
373
374         mali_platform_power_mode_change(device, MALI_POWER_MODE_ON);
375
376         if (NULL != device->driver &&
377                 NULL != device->driver->pm &&
378                 NULL != device->driver->pm->runtime_resume)
379         {
380                 /* Need to notify Mali driver about this event */
381                 ret = device->driver->pm->runtime_resume(device);
382         }
383
384         return ret;
385 }
386
387 static int mali_runtime_idle(struct device *device)
388 {
389         MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
390         if (NULL != device->driver &&
391                 NULL != device->driver->pm &&
392                 NULL != device->driver->pm->runtime_idle)
393         {
394                 int ret = 0;
395                 /* Need to notify Mali driver about this event */
396                 ret = device->driver->pm->runtime_idle(device);
397                 if (0 != ret)
398                 {
399                         return ret;
400                 }
401         }
402
403         return 1;
404 }
405
406 #endif /* USE_PM_NOTIFIER */
407 #endif /* CONFIG_PM_RUNTIME */