MALI: midgard: RK: fix compiling fail without CONFIG_REGULATOR defined
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / midgard / platform / rk / mali_kbase_config_rk.c
1 /*
2  *
3  * (C) COPYRIGHT ARM Limited. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  */
10
11 /* #define ENABLE_DEBUG_LOG */
12 #include "custom_log.h"
13
14 #include <mali_kbase.h>
15 #include <mali_kbase_defs.h>
16 #include <mali_kbase_config.h>
17 #include <backend/gpu/mali_kbase_pm_internal.h>
18
19 #include <linux/pm_runtime.h>
20 #include <linux/suspend.h>
21 #include <linux/of.h>
22 #include <linux/delay.h>
23
24 #include "mali_kbase_rk.h"
25
26 /**
27  * @file mali_kbase_config_rk.c
28  * 对 platform_config_of_rk 的具体实现.
29  *
30  * mali_device_driver 包含两部分 :
31  *      .DP : platform_dependent_part_in_mdd :
32  *              依赖 platform 部分,
33  *              源码在 <mdd_src_dir>/platform/<platform_name>/
34  *              在 mali_device_driver 内部,
35  *                      记为 platform_dependent_part,
36  *                      也被记为 platform_specific_code.
37  *      .DP : common_parts_in_mdd :
38  *              arm 实现的通用的部分,
39  *              源码在 <mdd_src_dir>/ 下.
40  *              在 mali_device_driver 内部, 记为 common_parts.
41  */
42
43 /*---------------------------------------------------------------------------*/
44
45 #ifdef CONFIG_REGULATOR
46 static int rk_pm_enable_regulator(struct kbase_device *kbdev);
47 static void rk_pm_disable_regulator(struct kbase_device *kbdev);
48 #else
49 static inline int rk_pm_enable_regulator(struct kbase_device *kbdev)
50 {
51         return 0;
52 }
53 static inline void rk_pm_disable_regulator(struct kbase_device *kbdev)
54 {
55 }
56 #endif
57
58 static int rk_pm_enable_clk(struct kbase_device *kbdev);
59
60 static void rk_pm_disable_clk(struct kbase_device *kbdev);
61
62 static int kbase_platform_rk_create_sysfs_files(struct device *dev);
63
64 static void kbase_platform_rk_remove_sysfs_files(struct device *dev);
65
66 /*---------------------------------------------------------------------------*/
67
68 static void rk_pm_power_off_delay_work(struct work_struct *work)
69 {
70         struct rk_context *platform =
71                 container_of(to_delayed_work(work), struct rk_context, work);
72         struct kbase_device *kbdev = platform->kbdev;
73
74         if (!platform->is_powered) {
75                 D("mali_dev is already powered off.");
76                 return;
77         }
78
79         if (pm_runtime_enabled(kbdev->dev)) {
80                 D("to put_sync_suspend mali_dev.");
81                 pm_runtime_put_sync_suspend(kbdev->dev);
82         }
83
84         rk_pm_disable_regulator(kbdev);
85
86         platform->is_powered = false;
87         KBASE_TIMELINE_GPU_POWER(kbdev, 0);
88 }
89
90 static int kbase_platform_rk_init(struct kbase_device *kbdev)
91 {
92         int ret = 0;
93         struct rk_context *platform;
94
95         platform = kzalloc(sizeof(*platform), GFP_KERNEL);
96         if (!platform) {
97                 E("err.");
98                 return -ENOMEM;
99         }
100
101         platform->is_powered = false;
102         platform->kbdev = kbdev;
103
104         platform->delay_ms = 200;
105         if (of_property_read_u32(kbdev->dev->of_node, "power-off-delay-ms",
106                                  &platform->delay_ms))
107                 W("power-off-delay-ms not available.");
108
109         platform->power_off_wq = create_freezable_workqueue("gpu_power_off_wq");
110         if (!platform->power_off_wq) {
111                 E("couldn't create workqueue");
112                 return -ENOMEM;
113         }
114         INIT_DEFERRABLE_WORK(&platform->work, rk_pm_power_off_delay_work);
115         platform->utilisation_period = DEFAULT_UTILISATION_PERIOD_IN_MS;
116
117         ret = kbase_platform_rk_create_sysfs_files(kbdev->dev);
118         if (ret) {
119                 E("fail to create sysfs_files. ret = %d.", ret);
120                 goto EXIT;
121         }
122
123         kbdev->platform_context = (void *)platform;
124         pm_runtime_enable(kbdev->dev);
125
126 EXIT:
127         return ret;
128 }
129
130 static void kbase_platform_rk_term(struct kbase_device *kbdev)
131 {
132         struct rk_context *platform =
133                 (struct rk_context *)kbdev->platform_context;
134
135         pm_runtime_disable(kbdev->dev);
136         kbdev->platform_context = NULL;
137
138         if (platform) {
139                 destroy_workqueue(platform->power_off_wq);
140                 platform->is_powered = false;
141                 platform->kbdev = NULL;
142                 kfree(platform);
143         }
144         kbase_platform_rk_remove_sysfs_files(kbdev->dev);
145 }
146
147 struct kbase_platform_funcs_conf platform_funcs = {
148         .platform_init_func = &kbase_platform_rk_init,
149         .platform_term_func = &kbase_platform_rk_term,
150 };
151
152 /*---------------------------------------------------------------------------*/
153
154 static int rk_pm_callback_runtime_on(struct kbase_device *kbdev)
155 {
156         return 0;
157 }
158
159 static void rk_pm_callback_runtime_off(struct kbase_device *kbdev)
160 {
161 }
162
163 static int rk_pm_callback_power_on(struct kbase_device *kbdev)
164 {
165         int ret = 1; /* Assume GPU has been powered off */
166         int err = 0;
167         struct rk_context *platform = get_rk_context(kbdev);
168
169         cancel_delayed_work_sync(&platform->work);
170
171         err = rk_pm_enable_clk(kbdev);
172         if (err) {
173                 E("failed to enable clk: %d", err);
174                 return err;
175         }
176
177         if (platform->is_powered) {
178                 D("mali_device is already powered.");
179                 return 0;
180         }
181
182         /* we must enable vdd_gpu before pd_gpu_in_chip. */
183         err = rk_pm_enable_regulator(kbdev);
184         if (err) {
185                 E("fail to enable regulator, err : %d.", err);
186                 return err;
187         }
188
189         /* 若 mali_dev 的 runtime_pm 是 enabled 的, 则... */
190         if (pm_runtime_enabled(kbdev->dev)) {
191                 D("to resume mali_dev syncly.");
192                 /* 对 pd_in_chip 的 on 操作,
193                  * 将在 pm_domain 的 runtime_pm_callbacks 中完成.
194                  */
195                 err = pm_runtime_get_sync(kbdev->dev);
196                 if (err < 0) {
197                         E("failed to runtime resume device: %d.", err);
198                         return err;
199                 } else if (err == 1) { /* runtime_pm_status is still active */
200                         D("chip has NOT been powered off, no need to re-init.");
201                         ret = 0;
202                 }
203         }
204
205         platform->is_powered = true;
206         KBASE_TIMELINE_GPU_POWER(kbdev, 1);
207
208         return ret;
209 }
210
211 static void rk_pm_callback_power_off(struct kbase_device *kbdev)
212 {
213         struct rk_context *platform = get_rk_context(kbdev);
214
215         rk_pm_disable_clk(kbdev);
216         queue_delayed_work(platform->power_off_wq, &platform->work,
217                            msecs_to_jiffies(platform->delay_ms));
218 }
219
220 int rk_kbase_device_runtime_init(struct kbase_device *kbdev)
221 {
222         return 0;
223 }
224
225 void rk_kbase_device_runtime_disable(struct kbase_device *kbdev)
226 {
227 }
228
229 struct kbase_pm_callback_conf pm_callbacks = {
230         .power_on_callback = rk_pm_callback_power_on,
231         .power_off_callback = rk_pm_callback_power_off,
232 #ifdef CONFIG_PM
233         .power_runtime_init_callback = rk_kbase_device_runtime_init,
234         .power_runtime_term_callback = rk_kbase_device_runtime_disable,
235         .power_runtime_on_callback = rk_pm_callback_runtime_on,
236         .power_runtime_off_callback = rk_pm_callback_runtime_off,
237 #else                           /* CONFIG_PM */
238         .power_runtime_init_callback = NULL,
239         .power_runtime_term_callback = NULL,
240         .power_runtime_on_callback = NULL,
241         .power_runtime_off_callback = NULL,
242 #endif                          /* CONFIG_PM */
243 };
244
245 int kbase_platform_early_init(void)
246 {
247         /* Nothing needed at this stage */
248         return 0;
249 }
250
251 /*---------------------------------------------------------------------------*/
252
253 void kbase_platform_rk_shutdown(struct kbase_device *kbdev)
254 {
255         I("to make vdd_gpu enabled for turning off pd_gpu in pm_framework.");
256         rk_pm_enable_regulator(kbdev);
257 }
258
259 /*---------------------------------------------------------------------------*/
260
261 #ifdef CONFIG_REGULATOR
262 static int rk_pm_enable_regulator(struct kbase_device *kbdev)
263 {
264         int ret = 0;
265
266         if (!kbdev->regulator) {
267                 W("no mali regulator control, no need to enable.");
268                 goto EXIT;
269         }
270
271         D("to enable regulator.");
272         ret = regulator_enable(kbdev->regulator);
273         if (ret) {
274                 E("fail to enable regulator, ret : %d.", ret);
275                 goto EXIT;
276         }
277
278 EXIT:
279         return ret;
280 }
281
282 static void rk_pm_disable_regulator(struct kbase_device *kbdev)
283 {
284         if (!(kbdev->regulator)) {
285                 W("no mali regulator control, no need to disable.");
286                 return;
287         }
288
289         D("to disable regulator.");
290         regulator_disable(kbdev->regulator);
291 }
292 #endif
293
294 static int rk_pm_enable_clk(struct kbase_device *kbdev)
295 {
296         int err = 0;
297
298         if (!(kbdev->clock)) {
299                 W("no mali clock control, no need to enable.");
300         } else {
301                 D("to enable clk.");
302                 err = clk_enable(kbdev->clock);
303                 if (err)
304                         E("failed to enable clk: %d.", err);
305         }
306
307         return err;
308 }
309
310 static void rk_pm_disable_clk(struct kbase_device *kbdev)
311 {
312         if (!(kbdev->clock)) {
313                 W("no mali clock control, no need to disable.");
314         } else {
315                 D("to disable clk.");
316                 clk_disable(kbdev->clock);
317         }
318 }
319
320 /*---------------------------------------------------------------------------*/
321
322 static ssize_t utilisation_period_show(struct device *dev,
323                                        struct device_attribute *attr,
324                                        char *buf)
325 {
326         struct kbase_device *kbdev = dev_get_drvdata(dev);
327         struct rk_context *platform = get_rk_context(kbdev);
328         ssize_t ret = 0;
329
330         ret += snprintf(buf, PAGE_SIZE, "%u\n", platform->utilisation_period);
331
332         return ret;
333 }
334
335 static ssize_t utilisation_period_store(struct device *dev,
336                                         struct device_attribute *attr,
337                                         const char *buf,
338                                         size_t count)
339 {
340         struct kbase_device *kbdev = dev_get_drvdata(dev);
341         struct rk_context *platform = get_rk_context(kbdev);
342         int ret = 0;
343
344         ret = kstrtouint(buf, 0, &platform->utilisation_period);
345         if (ret) {
346                 E("invalid input period : %s.", buf);
347                 return ret;
348         }
349         D("set utilisation_period to '%d'.", platform->utilisation_period);
350
351         return count;
352 }
353
354 static ssize_t utilisation_show(struct device *dev,
355                                 struct device_attribute *attr,
356                                 char *buf)
357 {
358         struct kbase_device *kbdev = dev_get_drvdata(dev);
359         struct rk_context *platform = get_rk_context(kbdev);
360         ssize_t ret = 0;
361         unsigned long period_in_us = platform->utilisation_period * 1000;
362         unsigned long total_time;
363         unsigned long busy_time;
364         unsigned long utilisation;
365
366         kbase_pm_reset_dvfs_utilisation(kbdev);
367         usleep_range(period_in_us, period_in_us + 100);
368         kbase_pm_get_dvfs_utilisation(kbdev, &total_time, &busy_time);
369         /* 'devfreq_dev_profile' instance registered to devfreq
370          * also uses kbase_pm_reset_dvfs_utilisation
371          * and kbase_pm_get_dvfs_utilisation.
372          * it's better to cat this file when DVFS is disabled.
373          */
374         D("total_time : %lu, busy_time : %lu.", total_time, busy_time);
375
376         utilisation = busy_time * 100 / total_time;
377         ret += snprintf(buf, PAGE_SIZE, "%ld\n", utilisation);
378
379         return ret;
380 }
381
382 static DEVICE_ATTR_RW(utilisation_period);
383 static DEVICE_ATTR_RO(utilisation);
384
385 static int kbase_platform_rk_create_sysfs_files(struct device *dev)
386 {
387         int ret = 0;
388
389         ret = device_create_file(dev, &dev_attr_utilisation_period);
390         if (ret) {
391                 E("fail to create sysfs file 'utilisation_period'.");
392                 goto out;
393         }
394
395         ret = device_create_file(dev, &dev_attr_utilisation);
396         if (ret) {
397                 E("fail to create sysfs file 'utilisation'.");
398                 goto remove_utilisation_period;
399         }
400
401         return 0;
402
403 remove_utilisation_period:
404         device_remove_file(dev, &dev_attr_utilisation_period);
405 out:
406         return ret;
407 }
408
409 static void kbase_platform_rk_remove_sysfs_files(struct device *dev)
410 {
411         device_remove_file(dev, &dev_attr_utilisation_period);
412         device_remove_file(dev, &dev_attr_utilisation);
413 }