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>
21 #include "mali_kbase_rk.h"
24 * @file mali_kbase_config_rk.c
25 * 对 platform_config_of_rk 的具体实现.
27 * mali_device_driver 包含两部分 :
28 * .DP : platform_dependent_part_in_mdd :
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 :
36 * 源码在 <mdd_src_dir>/ 下.
37 * 在 mali_device_driver 内部, 记为 common_parts.
40 /*---------------------------------------------------------------------------*/
42 static int rk_pm_enable_regulator(struct kbase_device *kbdev);
44 static void rk_pm_disable_regulator(struct kbase_device *kbdev);
46 static int rk_pm_enable_clk(struct kbase_device *kbdev);
48 static void rk_pm_disable_clk(struct kbase_device *kbdev);
50 /*---------------------------------------------------------------------------*/
52 static int kbase_platform_rk_init(struct kbase_device *kbdev)
54 struct rk_context *platform;
56 platform = kzalloc(sizeof(*platform), GFP_KERNEL);
62 platform->is_powered = false;
64 kbdev->platform_context = (void *)platform;
69 static void kbase_platform_rk_term(struct kbase_device *kbdev)
73 struct kbase_platform_funcs_conf platform_funcs = {
74 .platform_init_func = &kbase_platform_rk_init,
75 .platform_term_func = &kbase_platform_rk_term,
78 /*---------------------------------------------------------------------------*/
80 static int rk_pm_callback_runtime_on(struct kbase_device *kbdev)
85 static void rk_pm_callback_runtime_off(struct kbase_device *kbdev)
89 static int rk_pm_callback_power_on(struct kbase_device *kbdev)
91 int ret = 1; /* Assume GPU has been powered off */
93 struct rk_context *platform;
95 platform = (struct rk_context *)kbdev->platform_context;
96 if (platform->is_powered) {
97 W("mali_device is already powered.");
103 /* we must enable vdd_gpu before pd_gpu_in_chip. */
104 err = rk_pm_enable_regulator(kbdev);
106 E("fail to enable regulator, err : %d.", err);
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 中完成.
116 err = pm_runtime_get_sync(kbdev->dev);
118 E("failed to runtime resume device: %d.", 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.");
126 err = rk_pm_enable_clk(kbdev); /* clk is not relative to pd. */
128 E("failed to enable clk: %d", err);
132 platform->is_powered = true;
133 KBASE_TIMELINE_GPU_POWER(kbdev, 1);
138 static void rk_pm_callback_power_off(struct kbase_device *kbdev)
140 struct rk_context *platform =
141 (struct rk_context *)kbdev->platform_context;
143 if (!platform->is_powered) {
144 W("mali_dev is already powered off.");
150 platform->is_powered = false;
151 KBASE_TIMELINE_GPU_POWER(kbdev, 0);
153 rk_pm_disable_clk(kbdev);
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);
161 rk_pm_disable_regulator(kbdev);
164 int rk_kbase_device_runtime_init(struct kbase_device *kbdev)
166 pm_runtime_set_autosuspend_delay(kbdev->dev, 200);
167 pm_runtime_use_autosuspend(kbdev->dev);
169 /* no need to call pm_runtime_set_active here. */
171 D("to enable pm_runtime.");
172 pm_runtime_enable(kbdev->dev);
177 void rk_kbase_device_runtime_disable(struct kbase_device *kbdev)
179 D("to disable pm_runtime.");
180 pm_runtime_disable(kbdev->dev);
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,
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 */
199 int kbase_platform_early_init(void)
201 /* Nothing needed at this stage */
205 /*---------------------------------------------------------------------------*/
207 static int rk_pm_enable_regulator(struct kbase_device *kbdev)
211 if (!kbdev->regulator) {
212 W("no mali regulator control, no need to enable.");
216 D("to enable regulator.");
217 ret = regulator_enable(kbdev->regulator);
219 E("fail to enable regulator, ret : %d.", ret);
227 static void rk_pm_disable_regulator(struct kbase_device *kbdev)
229 if (!(kbdev->regulator)) {
230 W("no mali regulator control, no need to disable.");
234 D("to disable regulator.");
235 regulator_disable(kbdev->regulator);
238 static int rk_pm_enable_clk(struct kbase_device *kbdev)
242 if (!(kbdev->clock)) {
243 W("no mali clock control, no need to enable.");
246 err = clk_enable(kbdev->clock);
248 E("failed to enable clk: %d.", err);
254 static void rk_pm_disable_clk(struct kbase_device *kbdev)
256 if (!(kbdev->clock)) {
257 W("no mali clock control, no need to disable.");
259 D("to disable clk.");
260 clk_disable(kbdev->clock);