1 // SPDX-License-Identifier: GPL-2.0 or MIT
2 /* Copyright 2019 Collabora ltd. */
3
4 #include <linux/clk.h>
5 #include <linux/devfreq.h>
6 #include <linux/devfreq_cooling.h>
7 #include <linux/platform_device.h>
8 #include <linux/pm_opp.h>
9
10 #include <drm/drm_managed.h>
11 #include <drm/drm_print.h>
12
13 #include "panthor_devfreq.h"
14 #include "panthor_device.h"
15
16 /**
17 * struct panthor_devfreq - Device frequency management
18 */
19 struct panthor_devfreq {
20 /** @devfreq: devfreq device. */
21 struct devfreq *devfreq;
22
23 /** @gov_data: Governor data. */
24 struct devfreq_simple_ondemand_data gov_data;
25
26 /** @busy_time: Busy time. */
27 ktime_t busy_time;
28
29 /** @idle_time: Idle time. */
30 ktime_t idle_time;
31
32 /** @time_last_update: Last update time. */
33 ktime_t time_last_update;
34
35 /** @last_busy_state: True if the GPU was busy last time we updated the state. */
36 bool last_busy_state;
37
38 /**
39 * @lock: Lock used to protect busy_time, idle_time, time_last_update and
40 * last_busy_state.
41 *
42 * These fields can be accessed concurrently by panthor_devfreq_get_dev_status()
43 * and panthor_devfreq_record_{busy,idle}().
44 */
45 spinlock_t lock;
46 };
47
panthor_devfreq_update_utilization(struct panthor_devfreq * pdevfreq)48 static void panthor_devfreq_update_utilization(struct panthor_devfreq *pdevfreq)
49 {
50 ktime_t now, last;
51
52 now = ktime_get();
53 last = pdevfreq->time_last_update;
54
55 if (pdevfreq->last_busy_state)
56 pdevfreq->busy_time += ktime_sub(now, last);
57 else
58 pdevfreq->idle_time += ktime_sub(now, last);
59
60 pdevfreq->time_last_update = now;
61 }
62
panthor_devfreq_target(struct device * dev,unsigned long * freq,u32 flags)63 static int panthor_devfreq_target(struct device *dev, unsigned long *freq,
64 u32 flags)
65 {
66 struct dev_pm_opp *opp;
67 int err;
68
69 opp = devfreq_recommended_opp(dev, freq, flags);
70 if (IS_ERR(opp))
71 return PTR_ERR(opp);
72 dev_pm_opp_put(opp);
73
74 err = dev_pm_opp_set_rate(dev, *freq);
75
76 return err;
77 }
78
panthor_devfreq_reset(struct panthor_devfreq * pdevfreq)79 static void panthor_devfreq_reset(struct panthor_devfreq *pdevfreq)
80 {
81 pdevfreq->busy_time = 0;
82 pdevfreq->idle_time = 0;
83 pdevfreq->time_last_update = ktime_get();
84 }
85
panthor_devfreq_get_dev_status(struct device * dev,struct devfreq_dev_status * status)86 static int panthor_devfreq_get_dev_status(struct device *dev,
87 struct devfreq_dev_status *status)
88 {
89 struct panthor_device *ptdev = dev_get_drvdata(dev);
90 struct panthor_devfreq *pdevfreq = ptdev->devfreq;
91 unsigned long irqflags;
92
93 status->current_frequency = clk_get_rate(ptdev->clks.core);
94
95 spin_lock_irqsave(&pdevfreq->lock, irqflags);
96
97 panthor_devfreq_update_utilization(pdevfreq);
98
99 status->total_time = ktime_to_ns(ktime_add(pdevfreq->busy_time,
100 pdevfreq->idle_time));
101
102 status->busy_time = ktime_to_ns(pdevfreq->busy_time);
103
104 panthor_devfreq_reset(pdevfreq);
105
106 spin_unlock_irqrestore(&pdevfreq->lock, irqflags);
107
108 drm_dbg(&ptdev->base, "busy %lu total %lu %lu %% freq %lu MHz\n",
109 status->busy_time, status->total_time,
110 status->busy_time / (status->total_time / 100),
111 status->current_frequency / 1000 / 1000);
112
113 return 0;
114 }
115
panthor_devfreq_get_cur_freq(struct device * dev,unsigned long * freq)116 static int panthor_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
117 {
118 struct panthor_device *ptdev = dev_get_drvdata(dev);
119
120 *freq = clk_get_rate(ptdev->clks.core);
121
122 return 0;
123 }
124
125 static struct devfreq_dev_profile panthor_devfreq_profile = {
126 .timer = DEVFREQ_TIMER_DELAYED,
127 .polling_ms = 50, /* ~3 frames */
128 .target = panthor_devfreq_target,
129 .get_dev_status = panthor_devfreq_get_dev_status,
130 .get_cur_freq = panthor_devfreq_get_cur_freq,
131 };
132
panthor_devfreq_init(struct panthor_device * ptdev)133 int panthor_devfreq_init(struct panthor_device *ptdev)
134 {
135 /* There's actually 2 regulators (mali and sram), but the OPP core only
136 * supports one.
137 *
138 * We assume the sram regulator is coupled with the mali one and let
139 * the coupling logic deal with voltage updates.
140 */
141 static const char * const reg_names[] = { "mali", NULL };
142 struct thermal_cooling_device *cooling;
143 struct device *dev = ptdev->base.dev;
144 struct panthor_devfreq *pdevfreq;
145 struct opp_table *table;
146 struct dev_pm_opp *opp;
147 unsigned long cur_freq;
148 unsigned long freq = ULONG_MAX;
149 int ret;
150
151 pdevfreq = drmm_kzalloc(&ptdev->base, sizeof(*ptdev->devfreq), GFP_KERNEL);
152 if (!pdevfreq)
153 return -ENOMEM;
154
155 ptdev->devfreq = pdevfreq;
156
157 /*
158 * The power domain associated with the GPU may have already added an
159 * OPP table, complete with OPPs, as part of the platform bus
160 * initialization. If this is the case, the power domain is in charge of
161 * also controlling the performance, with a set_performance callback.
162 * Only add a new OPP table from DT if there isn't such a table present
163 * already.
164 */
165 table = dev_pm_opp_get_opp_table(dev);
166 if (IS_ERR_OR_NULL(table)) {
167 ret = devm_pm_opp_set_regulators(dev, reg_names);
168 if (ret && ret != -ENODEV) {
169 if (ret != -EPROBE_DEFER)
170 DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n");
171 return ret;
172 }
173
174 ret = devm_pm_opp_of_add_table(dev);
175 if (ret)
176 return ret;
177 } else {
178 dev_pm_opp_put_opp_table(table);
179 }
180
181 spin_lock_init(&pdevfreq->lock);
182
183 panthor_devfreq_reset(pdevfreq);
184
185 cur_freq = clk_get_rate(ptdev->clks.core);
186
187 /* Regulator coupling only takes care of synchronizing/balancing voltage
188 * updates, but the coupled regulator needs to be enabled manually.
189 *
190 * We use devm_regulator_get_enable_optional() and keep the sram supply
191 * enabled until the device is removed, just like we do for the mali
192 * supply, which is enabled when dev_pm_opp_set_opp(dev, opp) is called,
193 * and disabled when the opp_table is torn down, using the devm action.
194 *
195 * If we really care about disabling regulators on suspend, we should:
196 * - use devm_regulator_get_optional() here
197 * - call dev_pm_opp_set_opp(dev, NULL) before leaving this function
198 * (this disables the regulator passed to the OPP layer)
199 * - call dev_pm_opp_set_opp(dev, NULL) and
200 * regulator_disable(ptdev->regulators.sram) in
201 * panthor_devfreq_suspend()
202 * - call dev_pm_opp_set_opp(dev, default_opp) and
203 * regulator_enable(ptdev->regulators.sram) in
204 * panthor_devfreq_resume()
205 *
206 * But without knowing if it's beneficial or not (in term of power
207 * consumption), or how much it slows down the suspend/resume steps,
208 * let's just keep regulators enabled for the device lifetime.
209 */
210 ret = devm_regulator_get_enable_optional(dev, "sram");
211 if (ret && ret != -ENODEV) {
212 if (ret != -EPROBE_DEFER)
213 DRM_DEV_ERROR(dev, "Couldn't retrieve/enable sram supply\n");
214 return ret;
215 }
216
217 opp = devfreq_recommended_opp(dev, &cur_freq, 0);
218 if (IS_ERR(opp))
219 return PTR_ERR(opp);
220
221 panthor_devfreq_profile.initial_freq = cur_freq;
222
223 /*
224 * Set the recommend OPP this will enable and configure the regulator
225 * if any and will avoid a switch off by regulator_late_cleanup()
226 */
227 ret = dev_pm_opp_set_opp(dev, opp);
228 dev_pm_opp_put(opp);
229 if (ret) {
230 DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n");
231 return ret;
232 }
233
234 /* Find the fastest defined rate */
235 opp = dev_pm_opp_find_freq_floor(dev, &freq);
236 if (IS_ERR(opp))
237 return PTR_ERR(opp);
238 ptdev->fast_rate = freq;
239
240 dev_pm_opp_put(opp);
241
242 /*
243 * Setup default thresholds for the simple_ondemand governor.
244 * The values are chosen based on experiments.
245 */
246 pdevfreq->gov_data.upthreshold = 45;
247 pdevfreq->gov_data.downdifferential = 5;
248
249 pdevfreq->devfreq = devm_devfreq_add_device(dev, &panthor_devfreq_profile,
250 DEVFREQ_GOV_SIMPLE_ONDEMAND,
251 &pdevfreq->gov_data);
252 if (IS_ERR(pdevfreq->devfreq)) {
253 DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n");
254 ret = PTR_ERR(pdevfreq->devfreq);
255 pdevfreq->devfreq = NULL;
256 return ret;
257 }
258
259 cooling = devfreq_cooling_em_register(pdevfreq->devfreq, NULL);
260 if (IS_ERR(cooling))
261 DRM_DEV_INFO(dev, "Failed to register cooling device\n");
262
263 return 0;
264 }
265
panthor_devfreq_resume(struct panthor_device * ptdev)266 void panthor_devfreq_resume(struct panthor_device *ptdev)
267 {
268 struct panthor_devfreq *pdevfreq = ptdev->devfreq;
269
270 if (!pdevfreq->devfreq)
271 return;
272
273 panthor_devfreq_reset(pdevfreq);
274
275 drm_WARN_ON(&ptdev->base, devfreq_resume_device(pdevfreq->devfreq));
276 }
277
panthor_devfreq_suspend(struct panthor_device * ptdev)278 void panthor_devfreq_suspend(struct panthor_device *ptdev)
279 {
280 struct panthor_devfreq *pdevfreq = ptdev->devfreq;
281
282 if (!pdevfreq->devfreq)
283 return;
284
285 drm_WARN_ON(&ptdev->base, devfreq_suspend_device(pdevfreq->devfreq));
286 }
287
panthor_devfreq_record_busy(struct panthor_device * ptdev)288 void panthor_devfreq_record_busy(struct panthor_device *ptdev)
289 {
290 struct panthor_devfreq *pdevfreq = ptdev->devfreq;
291 unsigned long irqflags;
292
293 if (!pdevfreq->devfreq)
294 return;
295
296 spin_lock_irqsave(&pdevfreq->lock, irqflags);
297
298 panthor_devfreq_update_utilization(pdevfreq);
299 pdevfreq->last_busy_state = true;
300
301 spin_unlock_irqrestore(&pdevfreq->lock, irqflags);
302 }
303
panthor_devfreq_record_idle(struct panthor_device * ptdev)304 void panthor_devfreq_record_idle(struct panthor_device *ptdev)
305 {
306 struct panthor_devfreq *pdevfreq = ptdev->devfreq;
307 unsigned long irqflags;
308
309 if (!pdevfreq->devfreq)
310 return;
311
312 spin_lock_irqsave(&pdevfreq->lock, irqflags);
313
314 panthor_devfreq_update_utilization(pdevfreq);
315 pdevfreq->last_busy_state = false;
316
317 spin_unlock_irqrestore(&pdevfreq->lock, irqflags);
318 }
319
panthor_devfreq_get_freq(struct panthor_device * ptdev)320 unsigned long panthor_devfreq_get_freq(struct panthor_device *ptdev)
321 {
322 struct panthor_devfreq *pdevfreq = ptdev->devfreq;
323 unsigned long freq = 0;
324 int ret;
325
326 if (!pdevfreq->devfreq)
327 return 0;
328
329 ret = pdevfreq->devfreq->profile->get_cur_freq(ptdev->base.dev, &freq);
330 if (ret)
331 return 0;
332
333 return freq;
334 }
335