3 * (C) COPYRIGHT ARM Limited. All rights reserved.
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
11 /* #define ENABLE_DEBUG_LOG */
12 #include "custom_log.h"
14 #include <mali_kbase.h>
15 #include <mali_kbase_defs.h>
16 #include <mali_kbase_config.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/suspend.h>
22 #include "mali_kbase_rk.h"
25 * @file mali_kbase_config_rk.c
26 * 对 platform_config_of_rk 的具体实现.
28 * mali_device_driver 包含两部分 :
29 * .DP : platform_dependent_part_in_mdd :
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 :
37 * 源码在 <mdd_src_dir>/ 下.
38 * 在 mali_device_driver 内部, 记为 common_parts.
41 /*---------------------------------------------------------------------------*/
43 static int rk_pm_enable_regulator(struct kbase_device *kbdev);
45 static void rk_pm_disable_regulator(struct kbase_device *kbdev);
47 static int rk_pm_enable_clk(struct kbase_device *kbdev);
49 static void rk_pm_disable_clk(struct kbase_device *kbdev);
51 /*---------------------------------------------------------------------------*/
53 static void rk_pm_power_off_delay_work(struct work_struct *work)
55 struct rk_context *platform =
56 container_of(to_delayed_work(work), struct rk_context, work);
57 struct kbase_device *kbdev = platform->kbdev;
59 if (!platform->is_powered) {
60 D("mali_dev is already powered off.");
64 if (pm_runtime_enabled(kbdev->dev)) {
65 D("to put_sync_suspend mali_dev.");
66 pm_runtime_put_sync_suspend(kbdev->dev);
69 rk_pm_disable_regulator(kbdev);
71 platform->is_powered = false;
72 KBASE_TIMELINE_GPU_POWER(kbdev, 0);
75 static int kbase_platform_rk_init(struct kbase_device *kbdev)
77 struct rk_context *platform;
79 platform = kzalloc(sizeof(*platform), GFP_KERNEL);
85 platform->is_powered = false;
86 platform->kbdev = kbdev;
88 platform->delay_ms = 200;
89 if (of_property_read_u32(kbdev->dev->of_node, "power-off-delay-ms",
91 W("power-off-delay-ms not available.");
93 platform->power_off_wq = create_freezable_workqueue("gpu_power_off_wq");
94 if (!platform->power_off_wq) {
95 E("couldn't create workqueue");
98 INIT_DEFERRABLE_WORK(&platform->work, rk_pm_power_off_delay_work);
100 kbdev->platform_context = (void *)platform;
101 pm_runtime_enable(kbdev->dev);
106 static void kbase_platform_rk_term(struct kbase_device *kbdev)
108 struct rk_context *platform =
109 (struct rk_context *)kbdev->platform_context;
111 pm_runtime_disable(kbdev->dev);
112 kbdev->platform_context = NULL;
115 destroy_workqueue(platform->power_off_wq);
116 platform->is_powered = false;
117 platform->kbdev = NULL;
122 struct kbase_platform_funcs_conf platform_funcs = {
123 .platform_init_func = &kbase_platform_rk_init,
124 .platform_term_func = &kbase_platform_rk_term,
127 /*---------------------------------------------------------------------------*/
129 static int rk_pm_callback_runtime_on(struct kbase_device *kbdev)
134 static void rk_pm_callback_runtime_off(struct kbase_device *kbdev)
138 static int rk_pm_callback_power_on(struct kbase_device *kbdev)
140 int ret = 1; /* Assume GPU has been powered off */
142 struct rk_context *platform =
143 (struct rk_context *)kbdev->platform_context;
145 cancel_delayed_work_sync(&platform->work);
147 err = rk_pm_enable_clk(kbdev);
149 E("failed to enable clk: %d", err);
153 if (platform->is_powered) {
154 D("mali_device is already powered.");
158 /* we must enable vdd_gpu before pd_gpu_in_chip. */
159 err = rk_pm_enable_regulator(kbdev);
161 E("fail to enable regulator, err : %d.", err);
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 中完成.
171 err = pm_runtime_get_sync(kbdev->dev);
173 E("failed to runtime resume device: %d.", 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.");
181 platform->is_powered = true;
182 KBASE_TIMELINE_GPU_POWER(kbdev, 1);
187 static void rk_pm_callback_power_off(struct kbase_device *kbdev)
189 struct rk_context *platform =
190 (struct rk_context *)kbdev->platform_context;
192 rk_pm_disable_clk(kbdev);
193 queue_delayed_work(platform->power_off_wq, &platform->work,
194 msecs_to_jiffies(platform->delay_ms));
197 int rk_kbase_device_runtime_init(struct kbase_device *kbdev)
202 void rk_kbase_device_runtime_disable(struct kbase_device *kbdev)
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,
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 */
222 int kbase_platform_early_init(void)
224 /* Nothing needed at this stage */
228 /*---------------------------------------------------------------------------*/
230 static int rk_pm_enable_regulator(struct kbase_device *kbdev)
234 if (!kbdev->regulator) {
235 W("no mali regulator control, no need to enable.");
239 D("to enable regulator.");
240 ret = regulator_enable(kbdev->regulator);
242 E("fail to enable regulator, ret : %d.", ret);
250 static void rk_pm_disable_regulator(struct kbase_device *kbdev)
252 if (!(kbdev->regulator)) {
253 W("no mali regulator control, no need to disable.");
257 D("to disable regulator.");
258 regulator_disable(kbdev->regulator);
261 static int rk_pm_enable_clk(struct kbase_device *kbdev)
265 if (!(kbdev->clock)) {
266 W("no mali clock control, no need to enable.");
269 err = clk_enable(kbdev->clock);
271 E("failed to enable clk: %d.", err);
277 static void rk_pm_disable_clk(struct kbase_device *kbdev)
279 if (!(kbdev->clock)) {
280 W("no mali clock control, no need to disable.");
282 D("to disable clk.");
283 clk_disable(kbdev->clock);