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.
13 * implementation of platform_specific_code on rk platforms, such as rk3328h.
15 * mali_device_driver(MDD) includes 2 parts :
16 * .DP : platform_dependent_part :
17 * located in <mdd_src_dir>/mali/platform/<platform_name>/
19 * common part implemented by ARM.
22 #define ENABLE_DEBUG_LOG
23 #include "custom_log.h"
25 #include <linux/platform_device.h>
26 #include <linux/version.h>
29 #include <linux/clk.h>
30 #include <linux/regulator/consumer.h>
32 #include <linux/pm_runtime.h>
34 #include <linux/workqueue.h>
35 #include <linux/dma-mapping.h>
36 #include <linux/pm_runtime.h>
37 #include <linux/rockchip/cpu.h>
39 #include <linux/mali/mali_utgard.h>
40 #include "mali_kernel_common.h"
41 #include "../../common/mali_osk_mali.h"
43 /*---------------------------------------------------------------------------*/
47 /*---------------------------------------------------------------------------*/
50 * rk_platform_context_of_mali_device.
55 /* is the GPU powered on? */
59 struct rk_context *s_rk_context;
61 /*-------------------------------------------------------*/
63 static int rk_context_create_sysfs_files(struct device *dev)
70 static void rk_context_remove_sysfs_files(struct device *dev)
75 * Init rk_platform_context of mali_device.
77 static int rk_context_init(struct platform_device *pdev)
80 struct device *dev = &pdev->dev;
81 struct rk_context *platform; /* platform_context */
83 platform = kzalloc(sizeof(*platform), GFP_KERNEL);
86 return _MALI_OSK_ERR_NOMEM;
90 platform->is_powered = false;
92 ret = rk_context_create_sysfs_files(dev);
94 E("fail to create sysfs files, ret = %d", ret);
98 s_rk_context = platform;
100 pm_runtime_set_autosuspend_delay(dev, 1000);
101 pm_runtime_use_autosuspend(dev);
102 pm_runtime_enable(dev);
108 static void rk_context_deinit(struct platform_device *pdev)
110 struct device *dev = &pdev->dev;
111 struct rk_context *platform = s_rk_context;
113 pm_runtime_disable(dev);
117 rk_context_remove_sysfs_files(dev);
120 platform->is_powered = false;
121 platform->dev = NULL;
126 /*---------------------------------------------------------------------------*/
127 /* for devfreq cooling. */
129 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)
131 #define FALLBACK_STATIC_TEMPERATURE 55000
133 static struct thermal_zone_device *gpu_tz;
135 /* Calculate gpu static power example for reference */
136 static unsigned long rk_model_static_power(unsigned long voltage)
138 int temperature, temp;
139 int temp_squared, temp_cubed, temp_scaling_factor;
140 const unsigned long coefficient = (410UL << 20) / (729000000UL >> 10);
141 const unsigned long voltage_cubed = (voltage * voltage * voltage) >> 10;
142 unsigned long static_power;
147 ret = gpu_tz->ops->get_temp(gpu_tz, &temperature);
149 MALI_DEBUG_PRINT(2, ("fail to read temp: %d\n", ret));
150 temperature = FALLBACK_STATIC_TEMPERATURE;
153 temperature = FALLBACK_STATIC_TEMPERATURE;
156 /* Calculate the temperature scaling factor. To be applied to the
157 * voltage scaled power.
159 temp = temperature / 1000;
160 temp_squared = temp * temp;
161 temp_cubed = temp_squared * temp;
162 temp_scaling_factor =
164 - (80 * temp_squared)
168 static_power = (((coefficient * voltage_cubed) >> 20)
169 * temp_scaling_factor)
175 /* Calculate gpu dynamic power example for reference */
176 static unsigned long rk_model_dynamic_power(unsigned long freq,
177 unsigned long voltage)
179 /* The inputs: freq (f) is in Hz, and voltage (v) in mV.
180 * The coefficient (c) is in mW/(MHz mV mV).
182 * This function calculates the dynamic power after this formula:
183 * Pdyn (mW) = c (mW/(MHz*mV*mV)) * v (mV) * v (mV) * f (MHz)
185 const unsigned long v2 = (voltage * voltage) / 1000; /* m*(V*V) */
186 const unsigned long f_mhz = freq / 1000000; /* MHz */
187 const unsigned long coefficient = 3600; /* mW/(MHz*mV*mV) */
188 unsigned long dynamic_power;
190 dynamic_power = (coefficient * v2 * f_mhz) / 1000000; /* mW */
192 return dynamic_power;
195 struct devfreq_cooling_power rk_cooling_ops = {
196 .get_static_power = rk_model_static_power,
197 .get_dynamic_power = rk_model_dynamic_power,
201 /*---------------------------------------------------------------------------*/
205 static int rk_platform_enable_clk_gpu(struct device *dev)
208 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK)
209 struct mali_device *mdev = dev_get_drvdata(dev);
212 ret = clk_enable(mdev->clock);
217 static void rk_platform_disable_clk_gpu(struct device *dev)
219 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK)
220 struct mali_device *mdev = dev_get_drvdata(dev);
223 clk_disable(mdev->clock);
227 static int rk_platform_enable_gpu_regulator(struct device *dev)
230 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_REGULATOR)
231 struct mali_device *mdev = dev_get_drvdata(dev);
234 ret = regulator_enable(mdev->regulator);
239 static void rk_platform_disable_gpu_regulator(struct device *dev)
241 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_REGULATOR)
242 struct mali_device *mdev = dev_get_drvdata(dev);
245 regulator_disable(mdev->regulator);
249 static int rk_platform_power_on_gpu(struct device *dev)
253 ret = rk_platform_enable_clk_gpu(dev);
255 E("fail to enable clk_gpu, ret : %d.", ret);
256 goto fail_to_enable_clk;
259 ret = rk_platform_enable_gpu_regulator(dev);
261 E("fail to enable vdd_gpu, ret : %d.", ret);
262 goto fail_to_enable_regulator;
267 fail_to_enable_regulator:
268 rk_platform_disable_clk_gpu(dev);
274 static void rk_platform_power_off_gpu(struct device *dev)
276 rk_platform_disable_clk_gpu(dev);
277 rk_platform_disable_gpu_regulator(dev);
280 static int mali_runtime_suspend(struct device *device)
284 MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
286 if (device->driver &&
287 device->driver->pm &&
288 device->driver->pm->runtime_suspend) {
289 /* Need to notify Mali driver about this event */
290 ret = device->driver->pm->runtime_suspend(device);
293 rk_platform_power_off_gpu(device);
298 static int mali_runtime_resume(struct device *device)
302 MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
304 rk_platform_power_on_gpu(device);
306 if (device->driver &&
307 device->driver->pm &&
308 device->driver->pm->runtime_resume) {
309 /* Need to notify Mali driver about this event */
310 ret = device->driver->pm->runtime_resume(device);
316 static int mali_runtime_idle(struct device *device)
320 MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
322 if (device->driver &&
323 device->driver->pm &&
324 device->driver->pm->runtime_idle) {
325 /* Need to notify Mali driver about this event */
326 ret = device->driver->pm->runtime_idle(device);
331 pm_runtime_suspend(device);
337 static int mali_os_suspend(struct device *device)
341 MALI_DEBUG_PRINT(4, ("mali_os_suspend() called\n"));
343 if (device->driver &&
344 device->driver->pm &&
345 device->driver->pm->suspend) {
346 /* Need to notify Mali driver about this event */
347 ret = device->driver->pm->suspend(device);
350 rk_platform_power_off_gpu(device);
355 static int mali_os_resume(struct device *device)
359 MALI_DEBUG_PRINT(4, ("mali_os_resume() called\n"));
361 rk_platform_power_on_gpu(device);
363 if (device->driver &&
364 device->driver->pm &&
365 device->driver->pm->resume) {
366 /* Need to notify Mali driver about this event */
367 ret = device->driver->pm->resume(device);
373 static int mali_os_freeze(struct device *device)
377 MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
379 if (device->driver &&
380 device->driver->pm &&
381 device->driver->pm->freeze) {
382 /* Need to notify Mali driver about this event */
383 ret = device->driver->pm->freeze(device);
389 static int mali_os_thaw(struct device *device)
393 MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
395 if (device->driver &&
396 device->driver->pm &&
397 device->driver->pm->thaw) {
398 /* Need to notify Mali driver about this event */
399 ret = device->driver->pm->thaw(device);
405 static const struct dev_pm_ops mali_gpu_device_type_pm_ops = {
406 .suspend = mali_os_suspend,
407 .resume = mali_os_resume,
408 .freeze = mali_os_freeze,
409 .thaw = mali_os_thaw,
411 .runtime_suspend = mali_runtime_suspend,
412 .runtime_resume = mali_runtime_resume,
413 .runtime_idle = mali_runtime_idle,
417 static const struct device_type mali_gpu_device_device_type = {
418 .pm = &mali_gpu_device_type_pm_ops,
422 * platform_specific_data of platform_device of mali_gpu.
424 static const struct mali_gpu_device_data mali_gpu_data = {
425 .shared_mem_size = 1024 * 1024 * 1024, /* 1GB */
426 .max_job_runtime = 100, /* 100 ms */
427 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)
428 .gpu_cooling_ops = &rk_cooling_ops,
432 static void mali_platform_device_add_config(struct platform_device *pdev)
434 pdev->name = MALI_GPU_NAME_UTGARD,
436 pdev->dev.type = &mali_gpu_device_device_type;
437 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask,
438 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
441 /*---------------------------------------------------------------------------*/
442 /* platform_device_functions called by common_part. */
444 int mali_platform_device_init(struct platform_device *pdev)
448 mali_platform_device_add_config(pdev);
450 D("to add platform_specific_data to platform_device_of_mali.");
451 err = platform_device_add_data(pdev,
453 sizeof(mali_gpu_data));
455 E("fail to add platform_specific_data. err : %d.", err);
459 err = rk_context_init(pdev);
461 E("fail to init rk_context. err : %d.", err);
465 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)
466 /* Get thermal zone */
467 gpu_tz = thermal_zone_get_zone_by_name("gpu_thermal");
468 if (IS_ERR(gpu_tz)) {
469 W("Error getting gpu thermal zone (%ld), not yet ready?",
472 /* err = -EPROBE_DEFER; */
480 void mali_platform_device_deinit(struct platform_device *pdev)
482 MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
484 rk_context_deinit(pdev);