df15a9a6901b13106a7f5c20c030bb74e497835b
[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
18 #include <linux/pm_runtime.h>
19 #include <linux/suspend.h>
20 #include <linux/of.h>
21
22 #include "mali_kbase_rk.h"
23
24 /**
25  * @file mali_kbase_config_rk.c
26  * 对 platform_config_of_rk 的具体实现.
27  *
28  * mali_device_driver 包含两部分 :
29  *      .DP : platform_dependent_part_in_mdd :
30  *              依赖 platform 部分,
31  *              源码在 <mdd_src_dir>/platform/<platform_name>/
32  *              在 mali_device_driver 内部,
33  *                      记为 platform_dependent_part,
34  *                      也被记为 platform_specific_code.
35  *      .DP : common_parts_in_mdd :
36  *              arm 实现的通用的部分,
37  *              源码在 <mdd_src_dir>/ 下.
38  *              在 mali_device_driver 内部, 记为 common_parts.
39  */
40
41 /*---------------------------------------------------------------------------*/
42
43 static int rk_pm_enable_regulator(struct kbase_device *kbdev);
44
45 static void rk_pm_disable_regulator(struct kbase_device *kbdev);
46
47 static int rk_pm_enable_clk(struct kbase_device *kbdev);
48
49 static void rk_pm_disable_clk(struct kbase_device *kbdev);
50
51 /*---------------------------------------------------------------------------*/
52
53 static void rk_pm_power_off_delay_work(struct work_struct *work)
54 {
55         struct rk_context *platform =
56                 container_of(to_delayed_work(work), struct rk_context, work);
57         struct kbase_device *kbdev = platform->kbdev;
58
59         if (!platform->is_powered) {
60                 D("mali_dev is already powered off.");
61                 return;
62         }
63
64         if (pm_runtime_enabled(kbdev->dev)) {
65                 D("to put_sync_suspend mali_dev.");
66                 pm_runtime_put_sync_suspend(kbdev->dev);
67         }
68
69         rk_pm_disable_regulator(kbdev);
70
71         platform->is_powered = false;
72         KBASE_TIMELINE_GPU_POWER(kbdev, 0);
73 }
74
75 static int kbase_platform_rk_init(struct kbase_device *kbdev)
76 {
77         struct rk_context *platform;
78
79         platform = kzalloc(sizeof(*platform), GFP_KERNEL);
80         if (!platform) {
81                 E("err.");
82                 return -ENOMEM;
83         }
84
85         platform->is_powered = false;
86         platform->kbdev = kbdev;
87
88         platform->delay_ms = 200;
89         if (of_property_read_u32(kbdev->dev->of_node, "power-off-delay-ms",
90                                  &platform->delay_ms))
91                 W("power-off-delay-ms not available.");
92
93         platform->power_off_wq = create_freezable_workqueue("gpu_power_off_wq");
94         if (!platform->power_off_wq) {
95                 E("couldn't create workqueue");
96                 return -ENOMEM;
97         }
98         INIT_DEFERRABLE_WORK(&platform->work, rk_pm_power_off_delay_work);
99
100         kbdev->platform_context = (void *)platform;
101         pm_runtime_enable(kbdev->dev);
102
103         return 0;
104 }
105
106 static void kbase_platform_rk_term(struct kbase_device *kbdev)
107 {
108         struct rk_context *platform =
109                 (struct rk_context *)kbdev->platform_context;
110
111         pm_runtime_disable(kbdev->dev);
112         kbdev->platform_context = NULL;
113
114         if (platform) {
115                 destroy_workqueue(platform->power_off_wq);
116                 platform->is_powered = false;
117                 platform->kbdev = NULL;
118                 kfree(platform);
119         }
120 }
121
122 struct kbase_platform_funcs_conf platform_funcs = {
123         .platform_init_func = &kbase_platform_rk_init,
124         .platform_term_func = &kbase_platform_rk_term,
125 };
126
127 /*---------------------------------------------------------------------------*/
128
129 static int rk_pm_callback_runtime_on(struct kbase_device *kbdev)
130 {
131         return 0;
132 }
133
134 static void rk_pm_callback_runtime_off(struct kbase_device *kbdev)
135 {
136 }
137
138 static int rk_pm_callback_power_on(struct kbase_device *kbdev)
139 {
140         int ret = 1; /* Assume GPU has been powered off */
141         int err = 0;
142         struct rk_context *platform =
143                 (struct rk_context *)kbdev->platform_context;
144
145         cancel_delayed_work_sync(&platform->work);
146
147         err = rk_pm_enable_clk(kbdev);
148         if (err) {
149                 E("failed to enable clk: %d", err);
150                 return err;
151         }
152
153         if (platform->is_powered) {
154                 D("mali_device is already powered.");
155                 return 0;
156         }
157
158         /* we must enable vdd_gpu before pd_gpu_in_chip. */
159         err = rk_pm_enable_regulator(kbdev);
160         if (err) {
161                 E("fail to enable regulator, err : %d.", err);
162                 return err;
163         }
164
165         /* 若 mali_dev 的 runtime_pm 是 enabled 的, 则... */
166         if (pm_runtime_enabled(kbdev->dev)) {
167                 D("to resume mali_dev syncly.");
168                 /* 对 pd_in_chip 的 on 操作,
169                  * 将在 pm_domain 的 runtime_pm_callbacks 中完成.
170                  */
171                 err = pm_runtime_get_sync(kbdev->dev);
172                 if (err < 0) {
173                         E("failed to runtime resume device: %d.", err);
174                         return err;
175                 } else if (err == 1) { /* runtime_pm_status is still active */
176                         D("chip has NOT been powered off, no need to re-init.");
177                         ret = 0;
178                 }
179         }
180
181         platform->is_powered = true;
182         KBASE_TIMELINE_GPU_POWER(kbdev, 1);
183
184         return ret;
185 }
186
187 static void rk_pm_callback_power_off(struct kbase_device *kbdev)
188 {
189         struct rk_context *platform =
190                 (struct rk_context *)kbdev->platform_context;
191
192         rk_pm_disable_clk(kbdev);
193         queue_delayed_work(platform->power_off_wq, &platform->work,
194                            msecs_to_jiffies(platform->delay_ms));
195 }
196
197 int rk_kbase_device_runtime_init(struct kbase_device *kbdev)
198 {
199         return 0;
200 }
201
202 void rk_kbase_device_runtime_disable(struct kbase_device *kbdev)
203 {
204 }
205
206 struct kbase_pm_callback_conf pm_callbacks = {
207         .power_on_callback = rk_pm_callback_power_on,
208         .power_off_callback = rk_pm_callback_power_off,
209 #ifdef CONFIG_PM
210         .power_runtime_init_callback = rk_kbase_device_runtime_init,
211         .power_runtime_term_callback = rk_kbase_device_runtime_disable,
212         .power_runtime_on_callback = rk_pm_callback_runtime_on,
213         .power_runtime_off_callback = rk_pm_callback_runtime_off,
214 #else                           /* CONFIG_PM */
215         .power_runtime_init_callback = NULL,
216         .power_runtime_term_callback = NULL,
217         .power_runtime_on_callback = NULL,
218         .power_runtime_off_callback = NULL,
219 #endif                          /* CONFIG_PM */
220 };
221
222 int kbase_platform_early_init(void)
223 {
224         /* Nothing needed at this stage */
225         return 0;
226 }
227
228 /*---------------------------------------------------------------------------*/
229
230 static int rk_pm_enable_regulator(struct kbase_device *kbdev)
231 {
232         int ret = 0;
233
234         if (!kbdev->regulator) {
235                 W("no mali regulator control, no need to enable.");
236                 goto EXIT;
237         }
238
239         D("to enable regulator.");
240         ret = regulator_enable(kbdev->regulator);
241         if (ret) {
242                 E("fail to enable regulator, ret : %d.", ret);
243                 goto EXIT;
244         }
245
246 EXIT:
247         return ret;
248 }
249
250 static void rk_pm_disable_regulator(struct kbase_device *kbdev)
251 {
252         if (!(kbdev->regulator)) {
253                 W("no mali regulator control, no need to disable.");
254                 return;
255         }
256
257         D("to disable regulator.");
258         regulator_disable(kbdev->regulator);
259 }
260
261 static int rk_pm_enable_clk(struct kbase_device *kbdev)
262 {
263         int err = 0;
264
265         if (!(kbdev->clock)) {
266                 W("no mali clock control, no need to enable.");
267         } else {
268                 D("to enable clk.");
269                 err = clk_enable(kbdev->clock);
270                 if (err)
271                         E("failed to enable clk: %d.", err);
272         }
273
274         return err;
275 }
276
277 static void rk_pm_disable_clk(struct kbase_device *kbdev)
278 {
279         if (!(kbdev->clock)) {
280                 W("no mali clock control, no need to disable.");
281         } else {
282                 D("to disable clk.");
283                 clk_disable(kbdev->clock);
284         }
285 }
286