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