3 * (C) COPYRIGHT 2014-2015 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
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.
18 #include <mali_kbase.h>
19 #include <mali_kbase_config_defaults.h>
20 #include <backend/gpu/mali_kbase_pm_internal.h>
21 #ifdef CONFIG_DEVFREQ_THERMAL
22 #include <backend/gpu/mali_kbase_power_model_simple.h>
25 #include <linux/clk.h>
26 #include <linux/devfreq.h>
27 #ifdef CONFIG_DEVFREQ_THERMAL
28 #include <linux/devfreq_cooling.h>
31 #include <linux/version.h>
32 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
33 #include <linux/pm_opp.h>
34 #else /* Linux >= 3.13 */
35 /* In 3.13 the OPP include header file, types, and functions were all
36 * renamed. Use the old filename for the include, and define the new names to
37 * the old, when an old kernel is detected.
39 #include <linux/opp.h>
40 #define dev_pm_opp opp
41 #define dev_pm_opp_get_voltage opp_get_voltage
42 #define dev_pm_opp_get_opp_count opp_get_opp_count
43 #define dev_pm_opp_find_freq_ceil opp_find_freq_ceil
44 #endif /* Linux >= 3.13 */
48 kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
50 struct kbase_device *kbdev = dev_get_drvdata(dev);
51 struct dev_pm_opp *opp;
52 unsigned long freq = 0, last_freq = 0;
53 unsigned long voltage, last_voltage = 0;
59 opp = devfreq_recommended_opp(dev, &freq, flags);
60 voltage = dev_pm_opp_get_voltage(opp);
63 dev_err(dev, "Failed to get opp (%ld)\n", PTR_ERR(opp));
68 * Only update if there is a change of frequency
70 if (kbdev->current_freq == freq) {
75 #ifdef CONFIG_REGULATOR
76 if (kbdev->regulator && kbdev->current_voltage != voltage
77 && kbdev->current_freq < freq) {
78 last_voltage = regulator_get_voltage(kbdev->regulator);
79 if (last_voltage < 0) {
80 dev_err(dev, "Failed to get voltage (%lu)\n",
85 err = regulator_set_voltage(kbdev->regulator, voltage, voltage);
87 dev_err(dev, "Failed to increase voltage (%d)\n", err);
92 if (kbdev->current_freq > freq)
93 last_freq = clk_get_rate(kbdev->clock);
95 err = clk_set_rate(kbdev->clock, freq);
97 dev_err(dev, "Failed to set clock %lu (target %lu)\n",
100 regulator_set_voltage(kbdev->regulator, last_voltage,
105 #ifdef CONFIG_REGULATOR
106 if (kbdev->regulator && kbdev->current_voltage != voltage
107 && kbdev->current_freq > freq) {
108 err = regulator_set_voltage(kbdev->regulator, voltage, voltage);
110 clk_set_rate(kbdev->clock, last_freq);
111 dev_err(dev, "Failed to decrease voltage (%d)\n", err);
118 kbdev->current_voltage = voltage;
119 kbdev->current_freq = freq;
121 kbase_pm_reset_dvfs_utilisation(kbdev);
127 kbase_devfreq_cur_freq(struct device *dev, unsigned long *freq)
129 struct kbase_device *kbdev = dev_get_drvdata(dev);
131 *freq = kbdev->current_freq;
137 kbase_devfreq_status(struct device *dev, struct devfreq_dev_status *stat)
139 struct kbase_device *kbdev = dev_get_drvdata(dev);
141 stat->current_frequency = kbdev->current_freq;
143 kbase_pm_get_dvfs_utilisation(kbdev,
144 &stat->total_time, &stat->busy_time);
146 stat->private_data = NULL;
148 #ifdef CONFIG_DEVFREQ_THERMAL
149 #if 0 /* FIXME: devfreq_cooling has no last_status field */
150 if (kbdev->devfreq_cooling)
151 memcpy(&kbdev->devfreq_cooling->last_status, stat,
159 static int kbase_devfreq_init_freq_table(struct kbase_device *kbdev,
160 struct devfreq_dev_profile *dp)
164 unsigned long freq = 0;
165 struct dev_pm_opp *opp;
168 count = dev_pm_opp_get_opp_count(kbdev->dev);
175 dp->freq_table = kmalloc_array(count, sizeof(dp->freq_table[0]),
182 for (i = 0; i < count; i++, freq--) {
183 opp = dev_pm_opp_find_freq_floor(kbdev->dev, &freq);
187 dp->freq_table[i] = freq;
192 dev_warn(kbdev->dev, "Unable to enumerate all OPPs (%d!=%d\n",
200 static void kbase_devfreq_term_freq_table(struct kbase_device *kbdev)
202 struct devfreq_dev_profile *dp = kbdev->devfreq->profile;
204 kfree(dp->freq_table);
207 static void kbase_devfreq_exit(struct device *dev)
209 struct kbase_device *kbdev = dev_get_drvdata(dev);
211 kbase_devfreq_term_freq_table(kbdev);
214 static struct devfreq_simple_ondemand_data kbase_devfreq_ondemand_data = {
216 .downdifferential = 5,
219 int kbase_devfreq_init(struct kbase_device *kbdev)
221 struct devfreq_dev_profile *dp;
227 kbdev->current_freq = clk_get_rate(kbdev->clock);
229 dp = &kbdev->devfreq_profile;
231 dp->initial_freq = kbdev->current_freq;
232 dp->polling_ms = 100;
233 dp->target = kbase_devfreq_target;
234 dp->get_dev_status = kbase_devfreq_status;
235 dp->get_cur_freq = kbase_devfreq_cur_freq;
236 dp->exit = kbase_devfreq_exit;
238 if (kbase_devfreq_init_freq_table(kbdev, dp))
241 kbdev->devfreq = devfreq_add_device(kbdev->dev, dp,
243 &kbase_devfreq_ondemand_data);
244 if (IS_ERR(kbdev->devfreq)) {
245 kbase_devfreq_term_freq_table(kbdev);
246 return PTR_ERR(kbdev->devfreq);
249 err = devfreq_register_opp_notifier(kbdev->dev, kbdev->devfreq);
252 "Failed to register OPP notifier (%d)\n", err);
253 goto opp_notifier_failed;
256 #ifdef CONFIG_DEVFREQ_THERMAL
257 err = kbase_power_model_simple_init(kbdev);
258 if (err && err != -ENODEV && err != -EPROBE_DEFER) {
260 "Failed to initialize simple power model (%d)\n",
264 if (err == -EPROBE_DEFER)
266 if (err != -ENODEV) {
267 kbdev->devfreq_cooling = of_devfreq_cooling_register_power(
270 &power_model_simple_ops);
271 if (IS_ERR(kbdev->devfreq_cooling)) {
272 err = PTR_ERR(kbdev->devfreq_cooling);
274 "Failed to register cooling device (%d)\n",
285 #ifdef CONFIG_DEVFREQ_THERMAL
287 devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq);
288 #endif /* CONFIG_DEVFREQ_THERMAL */
290 if (devfreq_remove_device(kbdev->devfreq))
291 dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err);
293 kbdev->devfreq = NULL;
298 void kbase_devfreq_term(struct kbase_device *kbdev)
302 dev_dbg(kbdev->dev, "Term Mali devfreq\n");
304 #ifdef CONFIG_DEVFREQ_THERMAL
305 if (kbdev->devfreq_cooling)
306 devfreq_cooling_unregister(kbdev->devfreq_cooling);
309 devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq);
311 err = devfreq_remove_device(kbdev->devfreq);
313 dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err);
315 kbdev->devfreq = NULL;