MALI: utgard: RK: reconstruct platform specific code for devfreq DVFS
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / platform / rk / rk.c
1 /*
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
5  * ALL RIGHTS RESERVED
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.
9  */
10
11 /**
12  * @file rk.c
13  * implementation of platform_specific_code on rk platforms, such as rk3328h.
14  *
15  * mali_device_driver(MDD) includes 2 parts :
16  *      .DP : platform_dependent_part :
17  *              located in <mdd_src_dir>/mali/platform/<platform_name>/
18  *      .DP : common_part :
19  *              common part implemented by ARM.
20  */
21
22 #define ENABLE_DEBUG_LOG
23 #include "custom_log.h"
24
25 #include <linux/platform_device.h>
26 #include <linux/version.h>
27 #include <linux/pm.h>
28 #include <linux/of.h>
29 #include <linux/clk.h>
30 #include <linux/regulator/consumer.h>
31 #ifdef CONFIG_PM
32 #include <linux/pm_runtime.h>
33 #endif
34 #include <linux/workqueue.h>
35 #include <linux/dma-mapping.h>
36 #include <linux/pm_runtime.h>
37 #include <linux/rockchip/cpu.h>
38
39 #include <linux/mali/mali_utgard.h>
40 #include "mali_kernel_common.h"
41 #include "../../common/mali_osk_mali.h"
42
43 /*---------------------------------------------------------------------------*/
44
45 u32 mali_group_error;
46
47 /*---------------------------------------------------------------------------*/
48
49 /*
50  * rk_platform_context_of_mali_device.
51  */
52 struct rk_context {
53         /* mali device. */
54         struct device *dev;
55         /* is the GPU powered on?  */
56         bool is_powered;
57 };
58
59 struct rk_context *s_rk_context;
60
61 /*-------------------------------------------------------*/
62
63 static int rk_context_create_sysfs_files(struct device *dev)
64 {
65         int ret = 0;
66
67         return ret;
68 }
69
70 static void rk_context_remove_sysfs_files(struct device *dev)
71 {
72 }
73
74 /*
75  * Init rk_platform_context of mali_device.
76  */
77 static int rk_context_init(struct platform_device *pdev)
78 {
79         int ret = 0;
80         struct device *dev = &pdev->dev;
81         struct rk_context *platform; /* platform_context */
82
83         platform = kzalloc(sizeof(*platform), GFP_KERNEL);
84         if (!platform) {
85                 E("no mem.");
86                 return _MALI_OSK_ERR_NOMEM;
87         }
88
89         platform->dev = dev;
90         platform->is_powered = false;
91
92         ret = rk_context_create_sysfs_files(dev);
93         if (ret) {
94                 E("fail to create sysfs files, ret = %d", ret);
95                 goto EXIT;
96         }
97
98         s_rk_context = platform;
99
100         pm_runtime_set_autosuspend_delay(dev, 1000);
101         pm_runtime_use_autosuspend(dev);
102         pm_runtime_enable(dev);
103
104 EXIT:
105         return ret;
106 }
107
108 static void rk_context_deinit(struct platform_device *pdev)
109 {
110         struct device *dev = &pdev->dev;
111         struct rk_context *platform = s_rk_context;
112
113         pm_runtime_disable(dev);
114
115         s_rk_context = NULL;
116
117         rk_context_remove_sysfs_files(dev);
118
119         if (platform) {
120                 platform->is_powered = false;
121                 platform->dev = NULL;
122                 kfree(platform);
123         }
124 }
125
126 /*---------------------------------------------------------------------------*/
127 /* for devfreq cooling. */
128
129 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)
130
131 #define FALLBACK_STATIC_TEMPERATURE 55000
132
133 static struct thermal_zone_device *gpu_tz;
134
135 /* Calculate gpu static power example for reference */
136 static unsigned long rk_model_static_power(unsigned long voltage)
137 {
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;
143
144         if (gpu_tz) {
145                 int ret;
146
147                 ret = gpu_tz->ops->get_temp(gpu_tz, &temperature);
148                 if (ret) {
149                         MALI_DEBUG_PRINT(2, ("fail to read temp: %d\n", ret));
150                         temperature = FALLBACK_STATIC_TEMPERATURE;
151                 }
152         } else {
153                 temperature = FALLBACK_STATIC_TEMPERATURE;
154         }
155
156         /* Calculate the temperature scaling factor. To be applied to the
157          * voltage scaled power.
158          */
159         temp = temperature / 1000;
160         temp_squared = temp * temp;
161         temp_cubed = temp_squared * temp;
162         temp_scaling_factor =
163                 (2 * temp_cubed)
164                 - (80 * temp_squared)
165                 + (4700 * temp)
166                 + 32000;
167
168         static_power = (((coefficient * voltage_cubed) >> 20)
169                         * temp_scaling_factor)
170                        / 1000000;
171
172         return static_power;
173 }
174
175 /* Calculate gpu dynamic power example for reference */
176 static unsigned long rk_model_dynamic_power(unsigned long freq,
177                                             unsigned long voltage)
178 {
179         /* The inputs: freq (f) is in Hz, and voltage (v) in mV.
180          * The coefficient (c) is in mW/(MHz mV mV).
181          *
182          * This function calculates the dynamic power after this formula:
183          * Pdyn (mW) = c (mW/(MHz*mV*mV)) * v (mV) * v (mV) * f (MHz)
184          */
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;
189
190         dynamic_power = (coefficient * v2 * f_mhz) / 1000000; /* mW */
191
192         return dynamic_power;
193 }
194
195 struct devfreq_cooling_power rk_cooling_ops = {
196         .get_static_power = rk_model_static_power,
197         .get_dynamic_power = rk_model_dynamic_power,
198 };
199 #endif
200
201 /*---------------------------------------------------------------------------*/
202
203 #ifdef CONFIG_PM
204
205 static int rk_platform_enable_clk_gpu(struct device *dev)
206 {
207         int ret = 0;
208 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK)
209         struct mali_device *mdev = dev_get_drvdata(dev);
210
211         if (mdev->clock)
212                 ret = clk_enable(mdev->clock);
213 #endif
214         return ret;
215 }
216
217 static void rk_platform_disable_clk_gpu(struct device *dev)
218 {
219 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK)
220         struct mali_device *mdev = dev_get_drvdata(dev);
221
222         if (mdev->clock)
223                 clk_disable(mdev->clock);
224 #endif
225 }
226
227 static int rk_platform_enable_gpu_regulator(struct device *dev)
228 {
229         int ret = 0;
230 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_REGULATOR)
231         struct mali_device *mdev = dev_get_drvdata(dev);
232
233         if (mdev->regulator)
234                 ret = regulator_enable(mdev->regulator);
235 #endif
236         return ret;
237 }
238
239 static void rk_platform_disable_gpu_regulator(struct device *dev)
240 {
241 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_REGULATOR)
242         struct mali_device *mdev = dev_get_drvdata(dev);
243
244         if (mdev->regulator)
245                 regulator_disable(mdev->regulator);
246 #endif
247 }
248
249 static int rk_platform_power_on_gpu(struct device *dev)
250 {
251         int ret = 0;
252
253         ret = rk_platform_enable_clk_gpu(dev);
254         if (ret) {
255                 E("fail to enable clk_gpu, ret : %d.", ret);
256                 goto fail_to_enable_clk;
257         }
258
259         ret = rk_platform_enable_gpu_regulator(dev);
260         if (ret) {
261                 E("fail to enable vdd_gpu, ret : %d.", ret);
262                 goto fail_to_enable_regulator;
263         }
264
265         return 0;
266
267 fail_to_enable_regulator:
268         rk_platform_disable_clk_gpu(dev);
269
270 fail_to_enable_clk:
271         return ret;
272 }
273
274 static void rk_platform_power_off_gpu(struct device *dev)
275 {
276         rk_platform_disable_clk_gpu(dev);
277         rk_platform_disable_gpu_regulator(dev);
278 }
279
280 static int mali_runtime_suspend(struct device *device)
281 {
282         int ret = 0;
283
284         MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
285
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);
291         }
292
293         rk_platform_power_off_gpu(device);
294
295         return ret;
296 }
297
298 static int mali_runtime_resume(struct device *device)
299 {
300         int ret = 0;
301
302         MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
303
304         rk_platform_power_on_gpu(device);
305
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);
311         }
312
313         return ret;
314 }
315
316 static int mali_runtime_idle(struct device *device)
317 {
318         int ret = 0;
319
320         MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
321
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);
327                 if (ret)
328                         return ret;
329         }
330
331         pm_runtime_suspend(device);
332
333         return 0;
334 }
335 #endif
336
337 static int mali_os_suspend(struct device *device)
338 {
339         int ret = 0;
340
341         MALI_DEBUG_PRINT(4, ("mali_os_suspend() called\n"));
342
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);
348         }
349
350         rk_platform_power_off_gpu(device);
351
352         return ret;
353 }
354
355 static int mali_os_resume(struct device *device)
356 {
357         int ret = 0;
358
359         MALI_DEBUG_PRINT(4, ("mali_os_resume() called\n"));
360
361         rk_platform_power_on_gpu(device);
362
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);
368         }
369
370         return ret;
371 }
372
373 static int mali_os_freeze(struct device *device)
374 {
375         int ret = 0;
376
377         MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
378
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);
384         }
385
386         return ret;
387 }
388
389 static int mali_os_thaw(struct device *device)
390 {
391         int ret = 0;
392
393         MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
394
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);
400         }
401
402         return ret;
403 }
404
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,
410 #ifdef CONFIG_PM
411         .runtime_suspend = mali_runtime_suspend,
412         .runtime_resume = mali_runtime_resume,
413         .runtime_idle = mali_runtime_idle,
414 #endif
415 };
416
417 static const struct device_type mali_gpu_device_device_type = {
418         .pm = &mali_gpu_device_type_pm_ops,
419 };
420
421 /*
422  * platform_specific_data of platform_device of mali_gpu.
423  */
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,
429 #endif
430 };
431
432 static void mali_platform_device_add_config(struct platform_device *pdev)
433 {
434         pdev->name = MALI_GPU_NAME_UTGARD,
435         pdev->id = 0;
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);
439 }
440
441 /*---------------------------------------------------------------------------*/
442 /* platform_device_functions called by common_part. */
443
444 int mali_platform_device_init(struct platform_device *pdev)
445 {
446         int err = 0;
447
448         mali_platform_device_add_config(pdev);
449
450         D("to add platform_specific_data to platform_device_of_mali.");
451         err = platform_device_add_data(pdev,
452                                        &mali_gpu_data,
453                                        sizeof(mali_gpu_data));
454         if (err) {
455                 E("fail to add platform_specific_data. err : %d.", err);
456                 goto EXIT;
457         }
458
459         err = rk_context_init(pdev);
460         if (err) {
461                 E("fail to init rk_context. err : %d.", err);
462                 goto EXIT;
463         }
464
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?",
470                   PTR_ERR(gpu_tz));
471                 gpu_tz = NULL;
472                 /* err =  -EPROBE_DEFER; */
473         }
474 #endif
475
476 EXIT:
477         return err;
478 }
479
480 void mali_platform_device_deinit(struct platform_device *pdev)
481 {
482         MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
483
484         rk_context_deinit(pdev);
485 }