MALI: midgard: RK: slowdown clk_gpu before poweroff cores
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / midgard / backend / gpu / mali_kbase_devfreq.c
1 /*
2  *
3  * (C) COPYRIGHT 2014-2016 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  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15
16
17 #define ENABLE_DEBUG_LOG
18 #include "../../platform/rk/custom_log.h"
19
20
21 #include <mali_kbase.h>
22 #include <mali_kbase_config_defaults.h>
23 #include <backend/gpu/mali_kbase_pm_internal.h>
24 #ifdef CONFIG_DEVFREQ_THERMAL
25 #include <backend/gpu/mali_kbase_power_model_simple.h>
26 #endif
27
28 #include <linux/clk.h>
29 #include <linux/devfreq.h>
30 #ifdef CONFIG_DEVFREQ_THERMAL
31 #include <linux/devfreq_cooling.h>
32 #endif
33
34 #include <linux/version.h>
35 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
36 #include <linux/pm_opp.h>
37 #else /* Linux >= 3.13 */
38 /* In 3.13 the OPP include header file, types, and functions were all
39  * renamed. Use the old filename for the include, and define the new names to
40  * the old, when an old kernel is detected.
41  */
42 #include <linux/opp.h>
43 #define dev_pm_opp opp
44 #define dev_pm_opp_get_voltage opp_get_voltage
45 #define dev_pm_opp_get_opp_count opp_get_opp_count
46 #define dev_pm_opp_find_freq_ceil opp_find_freq_ceil
47 #endif /* Linux >= 3.13 */
48
49
50 static int
51 kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
52 {
53         struct kbase_device *kbdev = dev_get_drvdata(dev);
54         struct dev_pm_opp *opp;
55         unsigned long freq = 0;
56         unsigned long voltage;
57         int err = 0;
58
59         freq = *target_freq;
60
61         rcu_read_lock();
62         opp = devfreq_recommended_opp(dev, &freq, flags);
63         voltage = dev_pm_opp_get_voltage(opp);
64         rcu_read_unlock();
65         if (IS_ERR_OR_NULL(opp)) {
66                 dev_err(dev, "Failed to get opp (%ld)\n", PTR_ERR(opp));
67                 return PTR_ERR(opp);
68         }
69
70         /*
71          * Only update if there is a change of frequency
72          */
73         if (kbdev->current_freq == freq) {
74                 *target_freq = freq;
75                 return 0;
76         }
77
78 #ifdef CONFIG_REGULATOR
79         if (kbdev->regulator && kbdev->current_voltage != voltage
80                         && kbdev->current_freq < freq) {
81                 err = regulator_set_voltage(kbdev->regulator, voltage, voltage);
82                 if (err) {
83                         dev_err(dev, "Failed to increase voltage (%d)\n", err);
84                         return err;
85                 }
86         }
87 #endif
88
89         mutex_lock(&kbdev->mutex_for_clk);
90         if (!kbdev->is_power_off)
91                 err = clk_set_rate(kbdev->clock, freq);
92         kbdev->freq = freq;
93         mutex_unlock(&kbdev->mutex_for_clk);
94         if (err) {
95                 dev_err(dev, "Failed to set clock %lu (target %lu)\n",
96                                 freq, *target_freq);
97                 return err;
98         }
99
100 #ifdef CONFIG_REGULATOR
101         if (kbdev->regulator && kbdev->current_voltage != voltage
102                         && kbdev->current_freq > freq) {
103                 err = regulator_set_voltage(kbdev->regulator, voltage, voltage);
104                 if (err) {
105                         dev_err(dev, "Failed to decrease voltage (%d)\n", err);
106                         return err;
107                 }
108         }
109 #endif
110
111         *target_freq = freq;
112         kbdev->current_voltage = voltage;
113         kbdev->current_freq = freq;
114
115         kbase_pm_reset_dvfs_utilisation(kbdev);
116
117         return err;
118 }
119
120 static int
121 kbase_devfreq_cur_freq(struct device *dev, unsigned long *freq)
122 {
123         struct kbase_device *kbdev = dev_get_drvdata(dev);
124
125         *freq = kbdev->current_freq;
126
127         return 0;
128 }
129
130 static int
131 kbase_devfreq_status(struct device *dev, struct devfreq_dev_status *stat)
132 {
133         struct kbase_device *kbdev = dev_get_drvdata(dev);
134
135         stat->current_frequency = kbdev->current_freq;
136
137         kbase_pm_get_dvfs_utilisation(kbdev,
138                         &stat->total_time, &stat->busy_time);
139
140         stat->private_data = NULL;
141
142 #ifdef CONFIG_DEVFREQ_THERMAL
143 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
144         if (kbdev->devfreq_cooling)
145                 memcpy(&kbdev->devfreq_cooling->last_status, stat,
146                                 sizeof(*stat));
147 #endif
148 #endif
149
150         return 0;
151 }
152
153 static int kbase_devfreq_init_freq_table(struct kbase_device *kbdev,
154                 struct devfreq_dev_profile *dp)
155 {
156         int count;
157         int i = 0;
158         unsigned long freq = 0;
159         struct dev_pm_opp *opp;
160
161         rcu_read_lock();
162         count = dev_pm_opp_get_opp_count(kbdev->dev);
163         if (count < 0) {
164                 rcu_read_unlock();
165                 return count;
166         }
167         rcu_read_unlock();
168
169         dp->freq_table = kmalloc_array(count, sizeof(dp->freq_table[0]),
170                                 GFP_KERNEL);
171         if (!dp->freq_table)
172                 return -ENOMEM;
173
174         rcu_read_lock();
175         for (i = 0; i < count; i++, freq++) {
176                 opp = dev_pm_opp_find_freq_ceil(kbdev->dev, &freq);
177                 if (IS_ERR(opp))
178                         break;
179
180                 dp->freq_table[i] = freq;
181         }
182         rcu_read_unlock();
183
184         if (count != i)
185                 dev_warn(kbdev->dev, "Unable to enumerate all OPPs (%d!=%d\n",
186                                 count, i);
187
188         dp->max_state = i;
189
190         return 0;
191 }
192
193 static void kbase_devfreq_term_freq_table(struct kbase_device *kbdev)
194 {
195         struct devfreq_dev_profile *dp = kbdev->devfreq->profile;
196
197         kfree(dp->freq_table);
198 }
199
200 static void kbase_devfreq_exit(struct device *dev)
201 {
202         struct kbase_device *kbdev = dev_get_drvdata(dev);
203
204         kbase_devfreq_term_freq_table(kbdev);
205 }
206
207 int kbase_devfreq_init(struct kbase_device *kbdev)
208 {
209         struct devfreq_dev_profile *dp;
210         int err;
211
212         if (!kbdev->clock)
213                 return -ENODEV;
214
215         kbdev->current_freq = clk_get_rate(kbdev->clock);
216
217         dp = &kbdev->devfreq_profile;
218
219         dp->initial_freq = kbdev->current_freq;
220         /* .KP : set devfreq_dvfs_interval_in_ms */
221         dp->polling_ms = 20;
222         dp->target = kbase_devfreq_target;
223         dp->get_dev_status = kbase_devfreq_status;
224         dp->get_cur_freq = kbase_devfreq_cur_freq;
225         dp->exit = kbase_devfreq_exit;
226
227         if (kbase_devfreq_init_freq_table(kbdev, dp))
228                 return -EFAULT;
229
230         kbdev->devfreq = devfreq_add_device(kbdev->dev, dp,
231                                 "simple_ondemand", NULL);
232         if (IS_ERR(kbdev->devfreq)) {
233                 kbase_devfreq_term_freq_table(kbdev);
234                 return PTR_ERR(kbdev->devfreq);
235         }
236
237         err = devfreq_register_opp_notifier(kbdev->dev, kbdev->devfreq);
238         if (err) {
239                 dev_err(kbdev->dev,
240                         "Failed to register OPP notifier (%d)\n", err);
241                 goto opp_notifier_failed;
242         }
243
244 #ifdef CONFIG_DEVFREQ_THERMAL
245         err = kbase_power_model_simple_init(kbdev);
246         if (err && err != -ENODEV && err != -EPROBE_DEFER) {
247                 dev_err(kbdev->dev,
248                         "Failed to initialize simple power model (%d)\n",
249                         err);
250                 goto cooling_failed;
251         }
252         if (err == -EPROBE_DEFER)
253                 goto cooling_failed;
254         if (err != -ENODEV) {
255                 kbdev->devfreq_cooling = of_devfreq_cooling_register_power(
256                                 kbdev->dev->of_node,
257                                 kbdev->devfreq,
258                                 &power_model_simple_ops);
259                 if (IS_ERR_OR_NULL(kbdev->devfreq_cooling)) {
260                         err = PTR_ERR(kbdev->devfreq_cooling);
261                         dev_err(kbdev->dev,
262                                 "Failed to register cooling device (%d)\n",
263                                 err);
264                         goto cooling_failed;
265                 }
266         } else {
267                 err = 0;
268         }
269         I("success initing power_model_simple.");
270 #endif
271
272         return 0;
273
274 #ifdef CONFIG_DEVFREQ_THERMAL
275 cooling_failed:
276         devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq);
277 #endif /* CONFIG_DEVFREQ_THERMAL */
278 opp_notifier_failed:
279         if (devfreq_remove_device(kbdev->devfreq))
280                 dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err);
281         else
282                 kbdev->devfreq = NULL;
283
284         return err;
285 }
286
287 void kbase_devfreq_term(struct kbase_device *kbdev)
288 {
289         int err;
290
291         dev_dbg(kbdev->dev, "Term Mali devfreq\n");
292
293 #ifdef CONFIG_DEVFREQ_THERMAL
294         if (kbdev->devfreq_cooling)
295                 devfreq_cooling_unregister(kbdev->devfreq_cooling);
296 #endif
297
298         devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq);
299
300         err = devfreq_remove_device(kbdev->devfreq);
301         if (err)
302                 dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err);
303         else
304                 kbdev->devfreq = NULL;
305 }