2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2009-2010, 2012 ARM Limited
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
11 /*author by xxm 2012-12-1*/
13 #include <linux/platform_device.h>
14 #include <linux/version.h>
16 #ifdef CONFIG_PM_RUNTIME
17 #include <linux/pm_runtime.h>
19 #include <linux/mali/mali_utgard.h>
20 #include "mali_kernel_common.h"
22 #include "mali_platform.h"
24 #include <linux/workqueue.h>
25 #include <linux/dma-mapping.h>
26 #include <linux/rockchip/cpu.h>
28 static int num_cores_total;
29 static int num_cores_enabled;
30 static void mali_platform_device_release(struct device *device);
31 static int mali_os_suspend(struct device *device);
32 static int mali_os_resume(struct device *device);
33 static int mali_os_freeze(struct device *device);
34 static int mali_os_thaw(struct device *device);
35 #ifdef CONFIG_PM_RUNTIME
36 static int mali_runtime_suspend(struct device *device);
37 static int mali_runtime_resume(struct device *device);
38 static int mali_runtime_idle(struct device *device);
41 /*#include "arm_core_scaling.h"*/
42 void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data);
44 static struct work_struct wq_work;
46 static struct dev_pm_ops mali_gpu_device_type_pm_ops = {
47 .suspend = mali_os_suspend,
48 .resume = mali_os_resume,
49 .freeze = mali_os_freeze,
51 #ifdef CONFIG_PM_RUNTIME
52 .runtime_suspend = mali_runtime_suspend,
53 .runtime_resume = mali_runtime_resume,
54 .runtime_idle = mali_runtime_idle,
58 static struct device_type mali_gpu_device_device_type = {
59 .pm = &mali_gpu_device_type_pm_ops,
62 static u64 dma_dmamask = DMA_BIT_MASK(32);
64 static struct mali_gpu_device_data mali_gpu_data = {
65 .shared_mem_size = 1024* 1024 * 1024, /* 1GB */
66 .fb_start = 0x40000000,
67 .fb_size = 0xb1000000,
68 .utilization_interval = 0, /* 0ms */
69 .utilization_callback = mali_gpu_utilization_handler,
71 static void mali_platform_device_add_config(struct platform_device *pdev)
74 mali_gpu_device_device_type.pm = NULL;
76 pdev->dev.release = mali_platform_device_release;
77 pdev->dev.type = &mali_gpu_device_device_type;
78 pdev->dev.dma_mask = &dma_dmamask;
79 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
81 static void set_num_cores(struct work_struct *work)
83 int err = mali_perf_set_num_pp_cores(num_cores_enabled);
84 MALI_DEBUG_ASSERT(0 == err);
87 static void enable_one_core(void)
89 if (num_cores_enabled < num_cores_total) {
91 schedule_work(&wq_work);
92 MALI_DEBUG_PRINT(3, ("Core scaling: Enabling one more core\n"));
95 MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
96 MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
98 static void disable_one_core(void)
100 if (1 < num_cores_enabled) {
102 schedule_work(&wq_work);
103 MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
106 MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
107 MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
109 static void enable_max_num_cores(void)
111 if (num_cores_enabled < num_cores_total) {
112 num_cores_enabled = num_cores_total;
113 schedule_work(&wq_work);
114 MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n"));
117 MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
119 void mali_core_scaling_init(int num_pp_cores)
121 INIT_WORK(&wq_work, set_num_cores);
123 num_cores_total = num_pp_cores;
124 num_cores_enabled = num_pp_cores;
126 /* NOTE: Mali is not fully initialized at this point. */
128 void mali_core_scaling_term(void)
130 flush_scheduled_work();
132 #define PERCENT_OF(percent, max) ((int) ((percent)*(max)/100.0 + 0.5))
133 void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
136 * This function implements a very trivial PP core scaling algorithm.
138 * It is _NOT_ of production quality.
139 * The only intention behind this algorithm is to exercise and test the
140 * core scaling functionality of the driver.
141 * It is _NOT_ tuned for neither power saving nor performance!
143 * Other metrics than PP utilization need to be considered as well
144 * in order to make a good core scaling algorithm.
147 MALI_DEBUG_PRINT(3, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n",
148 data->utilization_gpu, data->utilization_gp,
149 data->utilization_pp, num_cores_enabled, num_cores_total));
151 /* NOTE: this function is normally called directly from the utilization callback which is in
154 if (PERCENT_OF(90, 256) < data->utilization_pp) {
155 enable_max_num_cores();
156 } else if (PERCENT_OF(50, 256) < data->utilization_pp) {
158 } else if (PERCENT_OF(40, 256) < data->utilization_pp) {
160 } else if (PERCENT_OF( 0, 256) < data->utilization_pp) {
166 int mali_platform_device_register(struct platform_device *pdev)
169 int num_pp_cores = 0;
170 MALI_PRINT(("mali_platform_device_register() called\n"));
174 mali_platform_device_add_config(pdev);
176 err = platform_device_add_data(pdev, &mali_gpu_data, sizeof(mali_gpu_data));
179 err = mali_platform_init();
181 #ifdef CONFIG_PM_RUNTIME
182 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
183 pm_runtime_set_autosuspend_delay(&(pdev->dev), 1000);
184 pm_runtime_use_autosuspend(&(pdev->dev));
186 pm_runtime_enable(&(pdev->dev));
188 mali_core_scaling_init(num_pp_cores);
194 void mali_platform_device_unregister(struct platform_device *pdev)
196 MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
198 mali_platform_deinit();
199 mali_core_scaling_term();
202 static void mali_platform_device_release(struct device *device)
204 MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
206 static int mali_os_suspend(struct device *device)
210 MALI_DEBUG_PRINT(2, ("mali_os_suspend() called\n"));
212 if (NULL != device->driver &&
213 NULL != device->driver->pm &&
214 NULL != device->driver->pm->suspend) {
215 /* Need to notify Mali driver about this event */
216 ret = device->driver->pm->suspend(device);
219 mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
224 static int mali_os_resume(struct device *device)
228 MALI_DEBUG_PRINT(2, ("mali_os_resume() called\n"));
230 mali_platform_power_mode_change(MALI_POWER_MODE_ON);
232 if (NULL != device->driver &&
233 NULL != device->driver->pm &&
234 NULL != device->driver->pm->resume) {
235 /* Need to notify Mali driver about this event */
236 ret = device->driver->pm->resume(device);
242 static int mali_os_freeze(struct device *device)
246 MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
248 if (NULL != device->driver &&
249 NULL != device->driver->pm &&
250 NULL != device->driver->pm->freeze) {
251 /* Need to notify Mali driver about this event */
252 ret = device->driver->pm->freeze(device);
258 static int mali_os_thaw(struct device *device)
262 MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
264 if (NULL != device->driver &&
265 NULL != device->driver->pm &&
266 NULL != device->driver->pm->thaw) {
267 /* Need to notify Mali driver about this event */
268 ret = device->driver->pm->thaw(device);
274 #ifdef CONFIG_PM_RUNTIME
275 static int mali_runtime_suspend(struct device *device)
278 MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
280 if (NULL != device->driver &&
281 NULL != device->driver->pm &&
282 NULL != device->driver->pm->runtime_suspend) {
283 /* Need to notify Mali driver about this event */
284 ret = device->driver->pm->runtime_suspend(device);
287 mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP);
292 static int mali_runtime_resume(struct device *device)
295 MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
297 mali_platform_power_mode_change(MALI_POWER_MODE_ON);
299 if (NULL != device->driver &&
300 NULL != device->driver->pm &&
301 NULL != device->driver->pm->runtime_resume) {
302 /* Need to notify Mali driver about this event */
303 ret = device->driver->pm->runtime_resume(device);
309 static int mali_runtime_idle(struct device *device)
312 MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
314 if (NULL != device->driver &&
315 NULL != device->driver->pm &&
316 NULL != device->driver->pm->runtime_idle) {
317 /* Need to notify Mali driver about this event */
318 ret = device->driver->pm->runtime_idle(device);
323 pm_runtime_suspend(device);
328 void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data)
330 mali_core_scaling_update(data);