xref: /linux/drivers/gpu/drm/panthor/panthor_devfreq.c (revision 6dfafbd0299a60bfb5d5e277fdf100037c7ded07)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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