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 static int num_cores_total;
27 static int num_cores_enabled;
28 static void mali_platform_device_release(struct device *device);
29 static int mali_os_suspend(struct device *device);
30 static int mali_os_resume(struct device *device);
31 static int mali_os_freeze(struct device *device);
32 static int mali_os_thaw(struct device *device);
33 #ifdef CONFIG_PM_RUNTIME
34 static int mali_runtime_suspend(struct device *device);
35 static int mali_runtime_resume(struct device *device);
36 static int mali_runtime_idle(struct device *device);
39 /*#include "arm_core_scaling.h"*/
40 void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data);
42 static struct work_struct wq_work;
44 static struct dev_pm_ops mali_gpu_device_type_pm_ops =
46 .suspend = mali_os_suspend,
47 .resume = mali_os_resume,
48 .freeze = mali_os_freeze,
50 #ifdef CONFIG_PM_RUNTIME
51 .runtime_suspend = mali_runtime_suspend,
52 .runtime_resume = mali_runtime_resume,
53 .runtime_idle = mali_runtime_idle,
57 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 =
66 .shared_mem_size = 1024* 1024 * 1024, /* 1GB */
67 .fb_start = 0x40000000,
68 .fb_size = 0xb1000000,
69 .utilization_interval = 0, /* 0ms */
70 .utilization_callback = mali_gpu_utilization_handler,
72 static void mali_platform_device_add_config(struct platform_device *pdev)
75 pdev->dev.release = mali_platform_device_release;
76 pdev->dev.type = &mali_gpu_device_device_type;
77 pdev->dev.dma_mask = &dma_dmamask;
78 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
80 static void set_num_cores(struct work_struct *work)
82 int err = mali_perf_set_num_pp_cores(num_cores_enabled);
83 MALI_DEBUG_ASSERT(0 == err);
86 static void enable_one_core(void)
88 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)
103 schedule_work(&wq_work);
104 MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
107 MALI_DEBUG_ASSERT( 1 <= num_cores_enabled);
108 MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
110 static void enable_max_num_cores(void)
112 if (num_cores_enabled < num_cores_total)
114 num_cores_enabled = num_cores_total;
115 schedule_work(&wq_work);
116 MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n"));
119 MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
121 void mali_core_scaling_init(int num_pp_cores)
123 INIT_WORK(&wq_work, set_num_cores);
125 num_cores_total = num_pp_cores;
126 num_cores_enabled = num_pp_cores;
128 /* NOTE: Mali is not fully initialized at this point. */
130 void mali_core_scaling_term(void)
132 flush_scheduled_work();
134 #define PERCENT_OF(percent, max) ((int) ((percent)*(max)/100.0 + 0.5))
135 void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
138 * This function implements a very trivial PP core scaling algorithm.
140 * It is _NOT_ of production quality.
141 * The only intention behind this algorithm is to exercise and test the
142 * core scaling functionality of the driver.
143 * It is _NOT_ tuned for neither power saving nor performance!
145 * Other metrics than PP utilization need to be considered as well
146 * in order to make a good core scaling algorithm.
149 MALI_DEBUG_PRINT(3, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n", data->utilization_gpu, data->utilization_gp, 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)
156 enable_max_num_cores();
158 else if (PERCENT_OF(50, 256) < data->utilization_pp)
162 else if (PERCENT_OF(40, 256) < data->utilization_pp)
166 else if (PERCENT_OF( 0, 256) < data->utilization_pp)
175 int mali_platform_device_register(struct platform_device *pdev)
178 int num_pp_cores = 0;
179 MALI_PRINT(("mali_platform_device_register() called\n"));
183 mali_platform_device_add_config(pdev);
185 err = platform_device_add_data(pdev, &mali_gpu_data, sizeof(mali_gpu_data));
189 err = mali_platform_init();
192 #ifdef CONFIG_PM_RUNTIME
193 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
194 pm_runtime_set_autosuspend_delay(&(pdev->dev), 1000);
195 pm_runtime_use_autosuspend(&(pdev->dev));
197 pm_runtime_enable(&(pdev->dev));
199 mali_core_scaling_init(num_pp_cores);
205 void mali_platform_device_unregister(struct platform_device *pdev)
207 MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
209 mali_platform_deinit();
210 mali_core_scaling_term();
213 static void mali_platform_device_release(struct device *device)
215 MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
217 static int mali_os_suspend(struct device *device)
221 MALI_DEBUG_PRINT(2, ("mali_os_suspend() called\n"));
223 if (NULL != device->driver &&
224 NULL != device->driver->pm &&
225 NULL != device->driver->pm->suspend)
227 /* Need to notify Mali driver about this event */
228 ret = device->driver->pm->suspend(device);
231 mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
236 static int mali_os_resume(struct device *device)
240 MALI_DEBUG_PRINT(2, ("mali_os_resume() called\n"));
242 mali_platform_power_mode_change(MALI_POWER_MODE_ON);
244 if (NULL != device->driver &&
245 NULL != device->driver->pm &&
246 NULL != device->driver->pm->resume)
248 /* Need to notify Mali driver about this event */
249 ret = device->driver->pm->resume(device);
255 static int mali_os_freeze(struct device *device)
259 MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
261 if (NULL != device->driver &&
262 NULL != device->driver->pm &&
263 NULL != device->driver->pm->freeze)
265 /* Need to notify Mali driver about this event */
266 ret = device->driver->pm->freeze(device);
272 static int mali_os_thaw(struct device *device)
276 MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
278 if (NULL != device->driver &&
279 NULL != device->driver->pm &&
280 NULL != device->driver->pm->thaw)
282 /* Need to notify Mali driver about this event */
283 ret = device->driver->pm->thaw(device);
289 #ifdef CONFIG_PM_RUNTIME
290 static int mali_runtime_suspend(struct device *device)
293 MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
295 if (NULL != device->driver &&
296 NULL != device->driver->pm &&
297 NULL != device->driver->pm->runtime_suspend)
299 /* Need to notify Mali driver about this event */
300 ret = device->driver->pm->runtime_suspend(device);
303 mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP);
308 static int mali_runtime_resume(struct device *device)
311 MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
313 mali_platform_power_mode_change(MALI_POWER_MODE_ON);
315 if (NULL != device->driver &&
316 NULL != device->driver->pm &&
317 NULL != device->driver->pm->runtime_resume)
319 /* Need to notify Mali driver about this event */
320 ret = device->driver->pm->runtime_resume(device);
326 static int mali_runtime_idle(struct device *device)
329 MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
331 if (NULL != device->driver &&
332 NULL != device->driver->pm &&
333 NULL != device->driver->pm->runtime_idle)
335 /* Need to notify Mali driver about this event */
336 ret = device->driver->pm->runtime_idle(device);
343 pm_runtime_suspend(device);
348 void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data)
350 mali_core_scaling_update(data);