1 /* drivers/gpu/mali400/mali/platform/pegasus-m400/exynos4.c
3 * Copyright 2011 by S.LSI. Samsung Electronics Inc.
4 * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea
6 * Samsung SoC Mali400 DVFS driver
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.
15 * Platform specific Mali driver functions for the exynos 4XXX based platforms
17 #include <linux/platform_device.h>
18 #include <linux/version.h>
20 #include <linux/suspend.h>
21 #include <linux/dma-mapping.h>
23 #ifdef CONFIG_PM_RUNTIME
24 #include <linux/pm_runtime.h>
27 #ifdef CONFIG_MALI_DVFS
28 #include "mali_kernel_utilization.h"
29 #endif /* CONFIG_MALI_DVFS */
31 #include <linux/mali/mali_utgard.h>
32 #include "mali_kernel_common.h"
33 #include "mali_kernel_linux.h"
38 #include "exynos4_pmm.h"
40 #if defined(CONFIG_PM_RUNTIME)
41 /* We does not need PM NOTIFIER in r3p2 DDK */
42 //#define USE_PM_NOTIFIER
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[];
52 extern struct platform_device s5pv310_device_pd[];
53 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) */
55 static void mali_platform_device_release(struct device *device);
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);
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);
70 #if defined(CONFIG_ARCH_S5PV310) && !defined(CONFIG_BOARD_HKDKC210)
72 /* This is for other SMDK boards */
73 #define MALI_BASE_IRQ 232
77 /* This is for the Odroid boards */
78 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
79 #define MALI_BASE_IRQ 182
81 #define MALI_BASE_IRQ 150
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
97 static struct resource mali_gpu_resources[] =
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)
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);
111 static struct notifier_block mali_pwr_notif_block = {
112 .notifier_call = mali_pwr_suspend_notifier
115 #endif /* CONFIG_PM_RUNTIME */
118 static struct dev_pm_ops mali_gpu_device_type_pm_ops =
120 #ifndef CONFIG_PM_RUNTIME
121 .suspend = mali_os_suspend,
122 .resume = mali_os_resume,
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,
134 #if defined(USE_PM_NOTIFIER)
135 static struct device_type mali_gpu_device_device_type =
137 .pm = &mali_gpu_device_type_pm_ops,
141 static struct platform_device mali_gpu_device =
143 .name = "mali_dev", /* MALI_SEC MALI_GPU_NAME_UTGARD, */
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,
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,
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.
160 .dev.type = &mali_gpu_device_device_type, /* We should probably use the pm_domain instead of type on newer kernels */
162 .dev.coherent_dma_mask = DMA_BIT_MASK(32),
165 static struct mali_gpu_device_data mali_gpu_data =
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,
174 int mali_platform_device_register(void)
178 MALI_DEBUG_PRINT(4, ("mali_platform_device_register() called\n"));
180 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
181 exynos_pm_add_dev_to_genpd(&mali_gpu_device, &exynos4_pd_g3d);
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]));
188 err = platform_device_add_data(&mali_gpu_device, &mali_gpu_data, sizeof(mali_gpu_data));
191 #ifdef CONFIG_PM_RUNTIME
192 #if defined(USE_PM_NOTIFIER)
193 err = register_pm_notifier(&mali_pwr_notif_block);
199 #endif /* CONFIG_PM_RUNTIME */
201 /* Register the platform device */
202 err = platform_device_register(&mali_gpu_device);
205 mali_platform_init(&(mali_gpu_device.dev));
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));
212 pm_runtime_enable(&(mali_gpu_device.dev));
219 #ifdef CONFIG_PM_RUNTIME
220 #if defined(USE_PM_NOTIFIER)
222 unregister_pm_notifier(&mali_pwr_notif_block);
224 #endif /* CONFIG_PM_RUNTIME */
225 platform_device_unregister(&mali_gpu_device);
231 void mali_platform_device_unregister(void)
233 MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
235 #ifdef CONFIG_PM_RUNTIME
236 #if defined(USE_PM_NOTIFIER)
237 unregister_pm_notifier(&mali_pwr_notif_block);
239 #endif /* CONFIG_PM_RUNTIME */
241 mali_platform_deinit(&(mali_gpu_device.dev));
243 platform_device_unregister(&mali_gpu_device);
246 static void mali_platform_device_release(struct device *device)
248 MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
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)
258 case PM_SUSPEND_PREPARE:
259 mali_pm_os_suspend();
260 err = mali_os_suspend(&(mali_platform_device->dev));
263 case PM_POST_SUSPEND:
264 err = mali_os_resume(&(mali_platform_device->dev));
273 static int mali_os_suspend(struct device *device)
276 MALI_DEBUG_PRINT(4, ("mali_os_suspend() called\n"));
278 #ifdef CONFIG_MALI_DVFS
279 mali_utilization_suspend();
282 if (NULL != device &&
283 NULL != device->driver &&
284 NULL != device->driver->pm &&
285 NULL != device->driver->pm->suspend)
287 /* Need to notify Mali driver about this event */
288 ret = device->driver->pm->suspend(device);
291 mali_platform_power_mode_change(device, MALI_POWER_MODE_DEEP_SLEEP);
296 static int mali_os_resume(struct device *device)
300 MALI_DEBUG_PRINT(4, ("mali_os_resume() called\n"));
301 #ifdef CONFIG_REGULATOR
302 mali_regulator_enable();
303 g3d_power_domain_control(1);
305 mali_platform_power_mode_change(device, MALI_POWER_MODE_ON);
307 if (NULL != device &&
308 NULL != device->driver &&
309 NULL != device->driver->pm &&
310 NULL != device->driver->pm->resume)
312 /* Need to notify Mali driver about this event */
313 ret = device->driver->pm->resume(device);
319 static int mali_os_freeze(struct device *device)
322 MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
324 if (NULL != device->driver &&
325 NULL != device->driver->pm &&
326 NULL != device->driver->pm->freeze)
328 /* Need to notify Mali driver about this event */
329 ret = device->driver->pm->freeze(device);
335 static int mali_os_thaw(struct device *device)
338 MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
340 if (NULL != device->driver &&
341 NULL != device->driver->pm &&
342 NULL != device->driver->pm->thaw)
344 /* Need to notify Mali driver about this event */
345 ret = device->driver->pm->thaw(device);
351 static int mali_runtime_suspend(struct device *device)
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)
360 /* Need to notify Mali driver about this event */
361 ret = device->driver->pm->runtime_suspend(device);
364 mali_platform_power_mode_change(device, MALI_POWER_MODE_LIGHT_SLEEP);
369 static int mali_runtime_resume(struct device *device)
372 MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
374 mali_platform_power_mode_change(device, MALI_POWER_MODE_ON);
376 if (NULL != device->driver &&
377 NULL != device->driver->pm &&
378 NULL != device->driver->pm->runtime_resume)
380 /* Need to notify Mali driver about this event */
381 ret = device->driver->pm->runtime_resume(device);
387 static int mali_runtime_idle(struct device *device)
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)
395 /* Need to notify Mali driver about this event */
396 ret = device->driver->pm->runtime_idle(device);
406 #endif /* USE_PM_NOTIFIER */
407 #endif /* CONFIG_PM_RUNTIME */