xref: /openbsd/sys/dev/pci/drm/i915/gt/intel_rps.c (revision ddf58b8f)
15ca02815Sjsg // SPDX-License-Identifier: MIT
2c349dbc7Sjsg /*
3c349dbc7Sjsg  * Copyright © 2019 Intel Corporation
4c349dbc7Sjsg  */
5c349dbc7Sjsg 
61bb76ff1Sjsg #include <linux/string_helpers.h>
71bb76ff1Sjsg 
8c349dbc7Sjsg #include <drm/i915_drm.h>
9c349dbc7Sjsg 
10f005ef32Sjsg #include "display/intel_display.h"
11f005ef32Sjsg #include "display/intel_display_irq.h"
12c349dbc7Sjsg #include "i915_drv.h"
131bb76ff1Sjsg #include "i915_irq.h"
14f005ef32Sjsg #include "i915_reg.h"
15ad8b1aafSjsg #include "intel_breadcrumbs.h"
16c349dbc7Sjsg #include "intel_gt.h"
17ad8b1aafSjsg #include "intel_gt_clock_utils.h"
18c349dbc7Sjsg #include "intel_gt_irq.h"
19f005ef32Sjsg #include "intel_gt_pm.h"
20c349dbc7Sjsg #include "intel_gt_pm_irq.h"
21f005ef32Sjsg #include "intel_gt_print.h"
221bb76ff1Sjsg #include "intel_gt_regs.h"
231bb76ff1Sjsg #include "intel_mchbar_regs.h"
241bb76ff1Sjsg #include "intel_pcode.h"
25c349dbc7Sjsg #include "intel_rps.h"
261bb76ff1Sjsg #include "vlv_sideband.h"
27c349dbc7Sjsg #ifdef __linux__
28c349dbc7Sjsg #include "../../../platform/x86/intel_ips.h"
29c349dbc7Sjsg #endif
30c349dbc7Sjsg 
31ad8b1aafSjsg #define BUSY_MAX_EI	20u /* ms */
32ad8b1aafSjsg 
33c349dbc7Sjsg /*
34c349dbc7Sjsg  * Lock protecting IPS related data structures
35c349dbc7Sjsg  */
36c349dbc7Sjsg static DEFINE_SPINLOCK(mchdev_lock);
37c349dbc7Sjsg 
rps_to_gt(struct intel_rps * rps)38c349dbc7Sjsg static struct intel_gt *rps_to_gt(struct intel_rps *rps)
39c349dbc7Sjsg {
40c349dbc7Sjsg 	return container_of(rps, struct intel_gt, rps);
41c349dbc7Sjsg }
42c349dbc7Sjsg 
rps_to_i915(struct intel_rps * rps)43c349dbc7Sjsg static struct drm_i915_private *rps_to_i915(struct intel_rps *rps)
44c349dbc7Sjsg {
45c349dbc7Sjsg 	return rps_to_gt(rps)->i915;
46c349dbc7Sjsg }
47c349dbc7Sjsg 
rps_to_uncore(struct intel_rps * rps)48c349dbc7Sjsg static struct intel_uncore *rps_to_uncore(struct intel_rps *rps)
49c349dbc7Sjsg {
50c349dbc7Sjsg 	return rps_to_gt(rps)->uncore;
51c349dbc7Sjsg }
52c349dbc7Sjsg 
rps_to_slpc(struct intel_rps * rps)535ca02815Sjsg static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps)
545ca02815Sjsg {
555ca02815Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
565ca02815Sjsg 
575ca02815Sjsg 	return &gt->uc.guc.slpc;
585ca02815Sjsg }
595ca02815Sjsg 
rps_uses_slpc(struct intel_rps * rps)605ca02815Sjsg static bool rps_uses_slpc(struct intel_rps *rps)
615ca02815Sjsg {
625ca02815Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
635ca02815Sjsg 
645ca02815Sjsg 	return intel_uc_uses_guc_slpc(&gt->uc);
655ca02815Sjsg }
665ca02815Sjsg 
rps_pm_sanitize_mask(struct intel_rps * rps,u32 mask)67c349dbc7Sjsg static u32 rps_pm_sanitize_mask(struct intel_rps *rps, u32 mask)
68c349dbc7Sjsg {
69c349dbc7Sjsg 	return mask & ~rps->pm_intrmsk_mbz;
70c349dbc7Sjsg }
71c349dbc7Sjsg 
set(struct intel_uncore * uncore,i915_reg_t reg,u32 val)725ca02815Sjsg static void set(struct intel_uncore *uncore, i915_reg_t reg, u32 val)
73c349dbc7Sjsg {
74c349dbc7Sjsg 	intel_uncore_write_fw(uncore, reg, val);
75c349dbc7Sjsg }
76c349dbc7Sjsg 
rps_timer(void * arg)77ad8b1aafSjsg static void rps_timer(void *arg)
78ad8b1aafSjsg {
79ad8b1aafSjsg 	struct intel_rps *rps = arg;
80f005ef32Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
81ad8b1aafSjsg 	struct intel_engine_cs *engine;
82ad8b1aafSjsg 	ktime_t dt, last, timestamp;
83ad8b1aafSjsg 	enum intel_engine_id id;
84ad8b1aafSjsg 	s64 max_busy[3] = {};
85ad8b1aafSjsg 
86ad8b1aafSjsg 	timestamp = 0;
87f005ef32Sjsg 	for_each_engine(engine, gt, id) {
88ad8b1aafSjsg 		s64 busy;
89ad8b1aafSjsg 		int i;
90ad8b1aafSjsg 
91ad8b1aafSjsg 		dt = intel_engine_get_busy_time(engine, &timestamp);
92ad8b1aafSjsg 		last = engine->stats.rps;
93ad8b1aafSjsg 		engine->stats.rps = dt;
94ad8b1aafSjsg 
95ad8b1aafSjsg 		busy = ktime_to_ns(ktime_sub(dt, last));
96ad8b1aafSjsg 		for (i = 0; i < ARRAY_SIZE(max_busy); i++) {
97ad8b1aafSjsg 			if (busy > max_busy[i])
98ad8b1aafSjsg 				swap(busy, max_busy[i]);
99ad8b1aafSjsg 		}
100ad8b1aafSjsg 	}
101ad8b1aafSjsg 	last = rps->pm_timestamp;
102ad8b1aafSjsg 	rps->pm_timestamp = timestamp;
103ad8b1aafSjsg 
104ad8b1aafSjsg 	if (intel_rps_is_active(rps)) {
105ad8b1aafSjsg 		s64 busy;
106ad8b1aafSjsg 		int i;
107ad8b1aafSjsg 
108ad8b1aafSjsg 		dt = ktime_sub(timestamp, last);
109ad8b1aafSjsg 
110ad8b1aafSjsg 		/*
111ad8b1aafSjsg 		 * Our goal is to evaluate each engine independently, so we run
112ad8b1aafSjsg 		 * at the lowest clocks required to sustain the heaviest
113ad8b1aafSjsg 		 * workload. However, a task may be split into sequential
114ad8b1aafSjsg 		 * dependent operations across a set of engines, such that
115ad8b1aafSjsg 		 * the independent contributions do not account for high load,
116ad8b1aafSjsg 		 * but overall the task is GPU bound. For example, consider
117ad8b1aafSjsg 		 * video decode on vcs followed by colour post-processing
118ad8b1aafSjsg 		 * on vecs, followed by general post-processing on rcs.
119ad8b1aafSjsg 		 * Since multi-engines being active does imply a single
120ad8b1aafSjsg 		 * continuous workload across all engines, we hedge our
121ad8b1aafSjsg 		 * bets by only contributing a factor of the distributed
122ad8b1aafSjsg 		 * load into our busyness calculation.
123ad8b1aafSjsg 		 */
124ad8b1aafSjsg 		busy = max_busy[0];
125ad8b1aafSjsg 		for (i = 1; i < ARRAY_SIZE(max_busy); i++) {
126ad8b1aafSjsg 			if (!max_busy[i])
127ad8b1aafSjsg 				break;
128ad8b1aafSjsg 
129ad8b1aafSjsg 			busy += div_u64(max_busy[i], 1 << i);
130ad8b1aafSjsg 		}
131f005ef32Sjsg 		GT_TRACE(gt,
132ad8b1aafSjsg 			 "busy:%lld [%d%%], max:[%lld, %lld, %lld], interval:%d\n",
133ad8b1aafSjsg 			 busy, (int)div64_u64(100 * busy, dt),
134ad8b1aafSjsg 			 max_busy[0], max_busy[1], max_busy[2],
135ad8b1aafSjsg 			 rps->pm_interval);
136ad8b1aafSjsg 
137ad8b1aafSjsg 		if (100 * busy > rps->power.up_threshold * dt &&
138ad8b1aafSjsg 		    rps->cur_freq < rps->max_freq_softlimit) {
139ad8b1aafSjsg 			rps->pm_iir |= GEN6_PM_RP_UP_THRESHOLD;
140ad8b1aafSjsg 			rps->pm_interval = 1;
141f005ef32Sjsg 			queue_work(gt->i915->unordered_wq, &rps->work);
142ad8b1aafSjsg 		} else if (100 * busy < rps->power.down_threshold * dt &&
143ad8b1aafSjsg 			   rps->cur_freq > rps->min_freq_softlimit) {
144ad8b1aafSjsg 			rps->pm_iir |= GEN6_PM_RP_DOWN_THRESHOLD;
145ad8b1aafSjsg 			rps->pm_interval = 1;
146f005ef32Sjsg 			queue_work(gt->i915->unordered_wq, &rps->work);
147ad8b1aafSjsg 		} else {
148ad8b1aafSjsg 			rps->last_adj = 0;
149ad8b1aafSjsg 		}
150ad8b1aafSjsg 
151ad8b1aafSjsg 		mod_timer(&rps->timer,
152ad8b1aafSjsg 			  jiffies + msecs_to_jiffies(rps->pm_interval));
153ad8b1aafSjsg 		rps->pm_interval = min(rps->pm_interval * 2, BUSY_MAX_EI);
154ad8b1aafSjsg 	}
155ad8b1aafSjsg }
156ad8b1aafSjsg 
rps_start_timer(struct intel_rps * rps)157ad8b1aafSjsg static void rps_start_timer(struct intel_rps *rps)
158ad8b1aafSjsg {
159ad8b1aafSjsg 	rps->pm_timestamp = ktime_sub(ktime_get(), rps->pm_timestamp);
160ad8b1aafSjsg 	rps->pm_interval = 1;
161ad8b1aafSjsg 	mod_timer(&rps->timer, jiffies + 1);
162ad8b1aafSjsg }
163ad8b1aafSjsg 
rps_stop_timer(struct intel_rps * rps)164ad8b1aafSjsg static void rps_stop_timer(struct intel_rps *rps)
165ad8b1aafSjsg {
166ad8b1aafSjsg 	del_timer_sync(&rps->timer);
167ad8b1aafSjsg 	rps->pm_timestamp = ktime_sub(ktime_get(), rps->pm_timestamp);
168ad8b1aafSjsg 	cancel_work_sync(&rps->work);
169ad8b1aafSjsg }
170ad8b1aafSjsg 
rps_pm_mask(struct intel_rps * rps,u8 val)171c349dbc7Sjsg static u32 rps_pm_mask(struct intel_rps *rps, u8 val)
172c349dbc7Sjsg {
173c349dbc7Sjsg 	u32 mask = 0;
174c349dbc7Sjsg 
175c349dbc7Sjsg 	/* We use UP_EI_EXPIRED interrupts for both up/down in manual mode */
176c349dbc7Sjsg 	if (val > rps->min_freq_softlimit)
177c349dbc7Sjsg 		mask |= (GEN6_PM_RP_UP_EI_EXPIRED |
178c349dbc7Sjsg 			 GEN6_PM_RP_DOWN_THRESHOLD |
179c349dbc7Sjsg 			 GEN6_PM_RP_DOWN_TIMEOUT);
180c349dbc7Sjsg 
181c349dbc7Sjsg 	if (val < rps->max_freq_softlimit)
182c349dbc7Sjsg 		mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD;
183c349dbc7Sjsg 
184ad8b1aafSjsg 	mask &= rps->pm_events;
185c349dbc7Sjsg 
186c349dbc7Sjsg 	return rps_pm_sanitize_mask(rps, ~mask);
187c349dbc7Sjsg }
188c349dbc7Sjsg 
rps_reset_ei(struct intel_rps * rps)189c349dbc7Sjsg static void rps_reset_ei(struct intel_rps *rps)
190c349dbc7Sjsg {
191c349dbc7Sjsg 	memset(&rps->ei, 0, sizeof(rps->ei));
192c349dbc7Sjsg }
193c349dbc7Sjsg 
rps_enable_interrupts(struct intel_rps * rps)194c349dbc7Sjsg static void rps_enable_interrupts(struct intel_rps *rps)
195c349dbc7Sjsg {
196c349dbc7Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
197ad8b1aafSjsg 
1985ca02815Sjsg 	GEM_BUG_ON(rps_uses_slpc(rps));
1995ca02815Sjsg 
200ad8b1aafSjsg 	GT_TRACE(gt, "interrupts:on rps->pm_events: %x, rps_pm_mask:%x\n",
201ad8b1aafSjsg 		 rps->pm_events, rps_pm_mask(rps, rps->last_freq));
202c349dbc7Sjsg 
203c349dbc7Sjsg 	rps_reset_ei(rps);
204c349dbc7Sjsg 
2051bb76ff1Sjsg 	spin_lock_irq(gt->irq_lock);
206c349dbc7Sjsg 	gen6_gt_pm_enable_irq(gt, rps->pm_events);
2071bb76ff1Sjsg 	spin_unlock_irq(gt->irq_lock);
208c349dbc7Sjsg 
209c349dbc7Sjsg 	intel_uncore_write(gt->uncore,
210c349dbc7Sjsg 			   GEN6_PMINTRMSK, rps_pm_mask(rps, rps->last_freq));
211c349dbc7Sjsg }
212c349dbc7Sjsg 
gen6_rps_reset_interrupts(struct intel_rps * rps)213c349dbc7Sjsg static void gen6_rps_reset_interrupts(struct intel_rps *rps)
214c349dbc7Sjsg {
215c349dbc7Sjsg 	gen6_gt_pm_reset_iir(rps_to_gt(rps), GEN6_PM_RPS_EVENTS);
216c349dbc7Sjsg }
217c349dbc7Sjsg 
gen11_rps_reset_interrupts(struct intel_rps * rps)218c349dbc7Sjsg static void gen11_rps_reset_interrupts(struct intel_rps *rps)
219c349dbc7Sjsg {
220c349dbc7Sjsg 	while (gen11_gt_reset_one_iir(rps_to_gt(rps), 0, GEN11_GTPM))
221c349dbc7Sjsg 		;
222c349dbc7Sjsg }
223c349dbc7Sjsg 
rps_reset_interrupts(struct intel_rps * rps)224c349dbc7Sjsg static void rps_reset_interrupts(struct intel_rps *rps)
225c349dbc7Sjsg {
226c349dbc7Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
227c349dbc7Sjsg 
2281bb76ff1Sjsg 	spin_lock_irq(gt->irq_lock);
2295ca02815Sjsg 	if (GRAPHICS_VER(gt->i915) >= 11)
230c349dbc7Sjsg 		gen11_rps_reset_interrupts(rps);
231c349dbc7Sjsg 	else
232c349dbc7Sjsg 		gen6_rps_reset_interrupts(rps);
233c349dbc7Sjsg 
234c349dbc7Sjsg 	rps->pm_iir = 0;
2351bb76ff1Sjsg 	spin_unlock_irq(gt->irq_lock);
236c349dbc7Sjsg }
237c349dbc7Sjsg 
rps_disable_interrupts(struct intel_rps * rps)238c349dbc7Sjsg static void rps_disable_interrupts(struct intel_rps *rps)
239c349dbc7Sjsg {
240c349dbc7Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
241c349dbc7Sjsg 
242c349dbc7Sjsg 	intel_uncore_write(gt->uncore,
243c349dbc7Sjsg 			   GEN6_PMINTRMSK, rps_pm_sanitize_mask(rps, ~0u));
244c349dbc7Sjsg 
2451bb76ff1Sjsg 	spin_lock_irq(gt->irq_lock);
246c349dbc7Sjsg 	gen6_gt_pm_disable_irq(gt, GEN6_PM_RPS_EVENTS);
2471bb76ff1Sjsg 	spin_unlock_irq(gt->irq_lock);
248c349dbc7Sjsg 
249c349dbc7Sjsg 	intel_synchronize_irq(gt->i915);
250c349dbc7Sjsg 
251c349dbc7Sjsg 	/*
252c349dbc7Sjsg 	 * Now that we will not be generating any more work, flush any
253c349dbc7Sjsg 	 * outstanding tasks. As we are called on the RPS idle path,
254c349dbc7Sjsg 	 * we will reset the GPU to minimum frequencies, so the current
255c349dbc7Sjsg 	 * state of the worker can be discarded.
256c349dbc7Sjsg 	 */
257c349dbc7Sjsg 	cancel_work_sync(&rps->work);
258c349dbc7Sjsg 
259c349dbc7Sjsg 	rps_reset_interrupts(rps);
260ad8b1aafSjsg 	GT_TRACE(gt, "interrupts:off\n");
261c349dbc7Sjsg }
262c349dbc7Sjsg 
263c349dbc7Sjsg static const struct cparams {
264c349dbc7Sjsg 	u16 i;
265c349dbc7Sjsg 	u16 t;
266c349dbc7Sjsg 	u16 m;
267c349dbc7Sjsg 	u16 c;
268c349dbc7Sjsg } cparams[] = {
269c349dbc7Sjsg 	{ 1, 1333, 301, 28664 },
270c349dbc7Sjsg 	{ 1, 1066, 294, 24460 },
271c349dbc7Sjsg 	{ 1, 800, 294, 25192 },
272c349dbc7Sjsg 	{ 0, 1333, 276, 27605 },
273c349dbc7Sjsg 	{ 0, 1066, 276, 27605 },
274c349dbc7Sjsg 	{ 0, 800, 231, 23784 },
275c349dbc7Sjsg };
276c349dbc7Sjsg 
gen5_rps_init(struct intel_rps * rps)277c349dbc7Sjsg static void gen5_rps_init(struct intel_rps *rps)
278c349dbc7Sjsg {
279c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
280c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
281c349dbc7Sjsg 	u8 fmax, fmin, fstart;
282c349dbc7Sjsg 	u32 rgvmodectl;
283c349dbc7Sjsg 	int c_m, i;
284c349dbc7Sjsg 
285c349dbc7Sjsg 	if (i915->fsb_freq <= 3200)
286c349dbc7Sjsg 		c_m = 0;
287c349dbc7Sjsg 	else if (i915->fsb_freq <= 4800)
288c349dbc7Sjsg 		c_m = 1;
289c349dbc7Sjsg 	else
290c349dbc7Sjsg 		c_m = 2;
291c349dbc7Sjsg 
292c349dbc7Sjsg 	for (i = 0; i < ARRAY_SIZE(cparams); i++) {
293c349dbc7Sjsg 		if (cparams[i].i == c_m && cparams[i].t == i915->mem_freq) {
294c349dbc7Sjsg 			rps->ips.m = cparams[i].m;
295c349dbc7Sjsg 			rps->ips.c = cparams[i].c;
296c349dbc7Sjsg 			break;
297c349dbc7Sjsg 		}
298c349dbc7Sjsg 	}
299c349dbc7Sjsg 
300c349dbc7Sjsg 	rgvmodectl = intel_uncore_read(uncore, MEMMODECTL);
301c349dbc7Sjsg 
302c349dbc7Sjsg 	/* Set up min, max, and cur for interrupt handling */
303c349dbc7Sjsg 	fmax = (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT;
304c349dbc7Sjsg 	fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
305c349dbc7Sjsg 	fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
306c349dbc7Sjsg 		MEMMODE_FSTART_SHIFT;
307ad8b1aafSjsg 	drm_dbg(&i915->drm, "fmax: %d, fmin: %d, fstart: %d\n",
308c349dbc7Sjsg 		fmax, fmin, fstart);
309c349dbc7Sjsg 
310c349dbc7Sjsg 	rps->min_freq = fmax;
311ad8b1aafSjsg 	rps->efficient_freq = fstart;
312c349dbc7Sjsg 	rps->max_freq = fmin;
313c349dbc7Sjsg }
314c349dbc7Sjsg 
315c349dbc7Sjsg static unsigned long
__ips_chipset_val(struct intel_ips * ips)316c349dbc7Sjsg __ips_chipset_val(struct intel_ips *ips)
317c349dbc7Sjsg {
318c349dbc7Sjsg 	struct intel_uncore *uncore =
319c349dbc7Sjsg 		rps_to_uncore(container_of(ips, struct intel_rps, ips));
320c349dbc7Sjsg 	unsigned long now = jiffies_to_msecs(jiffies), dt;
321c349dbc7Sjsg 	unsigned long result;
322c349dbc7Sjsg 	u64 total, delta;
323c349dbc7Sjsg 
324c349dbc7Sjsg 	lockdep_assert_held(&mchdev_lock);
325c349dbc7Sjsg 
326c349dbc7Sjsg 	/*
327c349dbc7Sjsg 	 * Prevent division-by-zero if we are asking too fast.
328c349dbc7Sjsg 	 * Also, we don't get interesting results if we are polling
329c349dbc7Sjsg 	 * faster than once in 10ms, so just return the saved value
330c349dbc7Sjsg 	 * in such cases.
331c349dbc7Sjsg 	 */
332c349dbc7Sjsg 	dt = now - ips->last_time1;
333c349dbc7Sjsg 	if (dt <= 10)
334c349dbc7Sjsg 		return ips->chipset_power;
335c349dbc7Sjsg 
336c349dbc7Sjsg 	/* FIXME: handle per-counter overflow */
337c349dbc7Sjsg 	total = intel_uncore_read(uncore, DMIEC);
338c349dbc7Sjsg 	total += intel_uncore_read(uncore, DDREC);
339c349dbc7Sjsg 	total += intel_uncore_read(uncore, CSIEC);
340c349dbc7Sjsg 
341c349dbc7Sjsg 	delta = total - ips->last_count1;
342c349dbc7Sjsg 
343c349dbc7Sjsg 	result = div_u64(div_u64(ips->m * delta, dt) + ips->c, 10);
344c349dbc7Sjsg 
345c349dbc7Sjsg 	ips->last_count1 = total;
346c349dbc7Sjsg 	ips->last_time1 = now;
347c349dbc7Sjsg 
348c349dbc7Sjsg 	ips->chipset_power = result;
349c349dbc7Sjsg 
350c349dbc7Sjsg 	return result;
351c349dbc7Sjsg }
352c349dbc7Sjsg 
ips_mch_val(struct intel_uncore * uncore)353c349dbc7Sjsg static unsigned long ips_mch_val(struct intel_uncore *uncore)
354c349dbc7Sjsg {
355c349dbc7Sjsg 	unsigned int m, x, b;
356c349dbc7Sjsg 	u32 tsfs;
357c349dbc7Sjsg 
358c349dbc7Sjsg 	tsfs = intel_uncore_read(uncore, TSFS);
359c349dbc7Sjsg 	x = intel_uncore_read8(uncore, TR1);
360c349dbc7Sjsg 
361c349dbc7Sjsg 	b = tsfs & TSFS_INTR_MASK;
362c349dbc7Sjsg 	m = (tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT;
363c349dbc7Sjsg 
364c349dbc7Sjsg 	return m * x / 127 - b;
365c349dbc7Sjsg }
366c349dbc7Sjsg 
_pxvid_to_vd(u8 pxvid)367c349dbc7Sjsg static int _pxvid_to_vd(u8 pxvid)
368c349dbc7Sjsg {
369c349dbc7Sjsg 	if (pxvid == 0)
370c349dbc7Sjsg 		return 0;
371c349dbc7Sjsg 
372c349dbc7Sjsg 	if (pxvid >= 8 && pxvid < 31)
373c349dbc7Sjsg 		pxvid = 31;
374c349dbc7Sjsg 
375c349dbc7Sjsg 	return (pxvid + 2) * 125;
376c349dbc7Sjsg }
377c349dbc7Sjsg 
pvid_to_extvid(struct drm_i915_private * i915,u8 pxvid)378c349dbc7Sjsg static u32 pvid_to_extvid(struct drm_i915_private *i915, u8 pxvid)
379c349dbc7Sjsg {
380c349dbc7Sjsg 	const int vd = _pxvid_to_vd(pxvid);
381c349dbc7Sjsg 
382c349dbc7Sjsg 	if (INTEL_INFO(i915)->is_mobile)
383c349dbc7Sjsg 		return max(vd - 1125, 0);
384c349dbc7Sjsg 
385c349dbc7Sjsg 	return vd;
386c349dbc7Sjsg }
387c349dbc7Sjsg 
__gen5_ips_update(struct intel_ips * ips)388c349dbc7Sjsg static void __gen5_ips_update(struct intel_ips *ips)
389c349dbc7Sjsg {
390c349dbc7Sjsg 	struct intel_uncore *uncore =
391c349dbc7Sjsg 		rps_to_uncore(container_of(ips, struct intel_rps, ips));
392c349dbc7Sjsg 	u64 now, delta, dt;
393c349dbc7Sjsg 	u32 count;
394c349dbc7Sjsg 
395c349dbc7Sjsg 	lockdep_assert_held(&mchdev_lock);
396c349dbc7Sjsg 
397c349dbc7Sjsg 	now = ktime_get_raw_ns();
398c349dbc7Sjsg 	dt = now - ips->last_time2;
399c349dbc7Sjsg 	do_div(dt, NSEC_PER_MSEC);
400c349dbc7Sjsg 
401c349dbc7Sjsg 	/* Don't divide by 0 */
402c349dbc7Sjsg 	if (dt <= 10)
403c349dbc7Sjsg 		return;
404c349dbc7Sjsg 
405c349dbc7Sjsg 	count = intel_uncore_read(uncore, GFXEC);
406c349dbc7Sjsg 	delta = count - ips->last_count2;
407c349dbc7Sjsg 
408c349dbc7Sjsg 	ips->last_count2 = count;
409c349dbc7Sjsg 	ips->last_time2 = now;
410c349dbc7Sjsg 
411c349dbc7Sjsg 	/* More magic constants... */
412c349dbc7Sjsg 	ips->gfx_power = div_u64(delta * 1181, dt * 10);
413c349dbc7Sjsg }
414c349dbc7Sjsg 
gen5_rps_update(struct intel_rps * rps)415c349dbc7Sjsg static void gen5_rps_update(struct intel_rps *rps)
416c349dbc7Sjsg {
417c349dbc7Sjsg 	spin_lock_irq(&mchdev_lock);
418c349dbc7Sjsg 	__gen5_ips_update(&rps->ips);
419c349dbc7Sjsg 	spin_unlock_irq(&mchdev_lock);
420c349dbc7Sjsg }
421c349dbc7Sjsg 
gen5_invert_freq(struct intel_rps * rps,unsigned int val)4225ca02815Sjsg static unsigned int gen5_invert_freq(struct intel_rps *rps,
4235ca02815Sjsg 				     unsigned int val)
4245ca02815Sjsg {
4255ca02815Sjsg 	/* Invert the frequency bin into an ips delay */
4265ca02815Sjsg 	val = rps->max_freq - val;
4275ca02815Sjsg 	val = rps->min_freq + val;
4285ca02815Sjsg 
4295ca02815Sjsg 	return val;
4305ca02815Sjsg }
4315ca02815Sjsg 
__gen5_rps_set(struct intel_rps * rps,u8 val)4325ca02815Sjsg static int __gen5_rps_set(struct intel_rps *rps, u8 val)
433c349dbc7Sjsg {
434c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
435c349dbc7Sjsg 	u16 rgvswctl;
436c349dbc7Sjsg 
437c349dbc7Sjsg 	lockdep_assert_held(&mchdev_lock);
438c349dbc7Sjsg 
439c349dbc7Sjsg 	rgvswctl = intel_uncore_read16(uncore, MEMSWCTL);
440c349dbc7Sjsg 	if (rgvswctl & MEMCTL_CMD_STS) {
441f005ef32Sjsg 		drm_dbg(&rps_to_i915(rps)->drm,
442f005ef32Sjsg 			"gpu busy, RCS change rejected\n");
4435ca02815Sjsg 		return -EBUSY; /* still busy with another command */
444c349dbc7Sjsg 	}
445c349dbc7Sjsg 
446c349dbc7Sjsg 	/* Invert the frequency bin into an ips delay */
4475ca02815Sjsg 	val = gen5_invert_freq(rps, val);
448c349dbc7Sjsg 
449c349dbc7Sjsg 	rgvswctl =
450c349dbc7Sjsg 		(MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
451c349dbc7Sjsg 		(val << MEMCTL_FREQ_SHIFT) |
452c349dbc7Sjsg 		MEMCTL_SFCAVM;
453c349dbc7Sjsg 	intel_uncore_write16(uncore, MEMSWCTL, rgvswctl);
454c349dbc7Sjsg 	intel_uncore_posting_read16(uncore, MEMSWCTL);
455c349dbc7Sjsg 
456c349dbc7Sjsg 	rgvswctl |= MEMCTL_CMD_STS;
457c349dbc7Sjsg 	intel_uncore_write16(uncore, MEMSWCTL, rgvswctl);
458c349dbc7Sjsg 
4595ca02815Sjsg 	return 0;
4605ca02815Sjsg }
4615ca02815Sjsg 
gen5_rps_set(struct intel_rps * rps,u8 val)4625ca02815Sjsg static int gen5_rps_set(struct intel_rps *rps, u8 val)
4635ca02815Sjsg {
4645ca02815Sjsg 	int err;
4655ca02815Sjsg 
4665ca02815Sjsg 	spin_lock_irq(&mchdev_lock);
4675ca02815Sjsg 	err = __gen5_rps_set(rps, val);
4685ca02815Sjsg 	spin_unlock_irq(&mchdev_lock);
4695ca02815Sjsg 
4705ca02815Sjsg 	return err;
471c349dbc7Sjsg }
472c349dbc7Sjsg 
intel_pxfreq(u32 vidfreq)473c349dbc7Sjsg static unsigned long intel_pxfreq(u32 vidfreq)
474c349dbc7Sjsg {
475c349dbc7Sjsg 	int div = (vidfreq & 0x3f0000) >> 16;
476c349dbc7Sjsg 	int post = (vidfreq & 0x3000) >> 12;
477c349dbc7Sjsg 	int pre = (vidfreq & 0x7);
478c349dbc7Sjsg 
479c349dbc7Sjsg 	if (!pre)
480c349dbc7Sjsg 		return 0;
481c349dbc7Sjsg 
482c349dbc7Sjsg 	return div * 133333 / (pre << post);
483c349dbc7Sjsg }
484c349dbc7Sjsg 
init_emon(struct intel_uncore * uncore)485c349dbc7Sjsg static unsigned int init_emon(struct intel_uncore *uncore)
486c349dbc7Sjsg {
487c349dbc7Sjsg 	u8 pxw[16];
488c349dbc7Sjsg 	int i;
489c349dbc7Sjsg 
490c349dbc7Sjsg 	/* Disable to program */
491c349dbc7Sjsg 	intel_uncore_write(uncore, ECR, 0);
492c349dbc7Sjsg 	intel_uncore_posting_read(uncore, ECR);
493c349dbc7Sjsg 
494c349dbc7Sjsg 	/* Program energy weights for various events */
495c349dbc7Sjsg 	intel_uncore_write(uncore, SDEW, 0x15040d00);
496c349dbc7Sjsg 	intel_uncore_write(uncore, CSIEW0, 0x007f0000);
497c349dbc7Sjsg 	intel_uncore_write(uncore, CSIEW1, 0x1e220004);
498c349dbc7Sjsg 	intel_uncore_write(uncore, CSIEW2, 0x04000004);
499c349dbc7Sjsg 
500c349dbc7Sjsg 	for (i = 0; i < 5; i++)
501c349dbc7Sjsg 		intel_uncore_write(uncore, PEW(i), 0);
502c349dbc7Sjsg 	for (i = 0; i < 3; i++)
503c349dbc7Sjsg 		intel_uncore_write(uncore, DEW(i), 0);
504c349dbc7Sjsg 
505c349dbc7Sjsg 	/* Program P-state weights to account for frequency power adjustment */
506c349dbc7Sjsg 	for (i = 0; i < 16; i++) {
507c349dbc7Sjsg 		u32 pxvidfreq = intel_uncore_read(uncore, PXVFREQ(i));
508c349dbc7Sjsg 		unsigned int freq = intel_pxfreq(pxvidfreq);
509c349dbc7Sjsg 		unsigned int vid =
510c349dbc7Sjsg 			(pxvidfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT;
511c349dbc7Sjsg 		unsigned int val;
512c349dbc7Sjsg 
513c349dbc7Sjsg 		val = vid * vid * freq / 1000 * 255;
514c349dbc7Sjsg 		val /= 127 * 127 * 900;
515c349dbc7Sjsg 
516c349dbc7Sjsg 		pxw[i] = val;
517c349dbc7Sjsg 	}
518c349dbc7Sjsg 	/* Render standby states get 0 weight */
519c349dbc7Sjsg 	pxw[14] = 0;
520c349dbc7Sjsg 	pxw[15] = 0;
521c349dbc7Sjsg 
522c349dbc7Sjsg 	for (i = 0; i < 4; i++) {
523c349dbc7Sjsg 		intel_uncore_write(uncore, PXW(i),
524c349dbc7Sjsg 				   pxw[i * 4 + 0] << 24 |
525c349dbc7Sjsg 				   pxw[i * 4 + 1] << 16 |
526c349dbc7Sjsg 				   pxw[i * 4 + 2] <<  8 |
527c349dbc7Sjsg 				   pxw[i * 4 + 3] <<  0);
528c349dbc7Sjsg 	}
529c349dbc7Sjsg 
530c349dbc7Sjsg 	/* Adjust magic regs to magic values (more experimental results) */
531c349dbc7Sjsg 	intel_uncore_write(uncore, OGW0, 0);
532c349dbc7Sjsg 	intel_uncore_write(uncore, OGW1, 0);
533c349dbc7Sjsg 	intel_uncore_write(uncore, EG0, 0x00007f00);
534c349dbc7Sjsg 	intel_uncore_write(uncore, EG1, 0x0000000e);
535c349dbc7Sjsg 	intel_uncore_write(uncore, EG2, 0x000e0000);
536c349dbc7Sjsg 	intel_uncore_write(uncore, EG3, 0x68000300);
537c349dbc7Sjsg 	intel_uncore_write(uncore, EG4, 0x42000000);
538c349dbc7Sjsg 	intel_uncore_write(uncore, EG5, 0x00140031);
539c349dbc7Sjsg 	intel_uncore_write(uncore, EG6, 0);
540c349dbc7Sjsg 	intel_uncore_write(uncore, EG7, 0);
541c349dbc7Sjsg 
542c349dbc7Sjsg 	for (i = 0; i < 8; i++)
543c349dbc7Sjsg 		intel_uncore_write(uncore, PXWL(i), 0);
544c349dbc7Sjsg 
545c349dbc7Sjsg 	/* Enable PMON + select events */
546c349dbc7Sjsg 	intel_uncore_write(uncore, ECR, 0x80000019);
547c349dbc7Sjsg 
548c349dbc7Sjsg 	return intel_uncore_read(uncore, LCFUSE02) & LCFUSE_HIV_MASK;
549c349dbc7Sjsg }
550c349dbc7Sjsg 
gen5_rps_enable(struct intel_rps * rps)551c349dbc7Sjsg static bool gen5_rps_enable(struct intel_rps *rps)
552c349dbc7Sjsg {
5535ca02815Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
554c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
555c349dbc7Sjsg 	u8 fstart, vstart;
556c349dbc7Sjsg 	u32 rgvmodectl;
557c349dbc7Sjsg 
558c349dbc7Sjsg 	spin_lock_irq(&mchdev_lock);
559c349dbc7Sjsg 
560c349dbc7Sjsg 	rgvmodectl = intel_uncore_read(uncore, MEMMODECTL);
561c349dbc7Sjsg 
562c349dbc7Sjsg 	/* Enable temp reporting */
563c349dbc7Sjsg 	intel_uncore_write16(uncore, PMMISC,
564c349dbc7Sjsg 			     intel_uncore_read16(uncore, PMMISC) | MCPPCE_EN);
565c349dbc7Sjsg 	intel_uncore_write16(uncore, TSC1,
566c349dbc7Sjsg 			     intel_uncore_read16(uncore, TSC1) | TSE);
567c349dbc7Sjsg 
568c349dbc7Sjsg 	/* 100ms RC evaluation intervals */
569c349dbc7Sjsg 	intel_uncore_write(uncore, RCUPEI, 100000);
570c349dbc7Sjsg 	intel_uncore_write(uncore, RCDNEI, 100000);
571c349dbc7Sjsg 
572c349dbc7Sjsg 	/* Set max/min thresholds to 90ms and 80ms respectively */
573c349dbc7Sjsg 	intel_uncore_write(uncore, RCBMAXAVG, 90000);
574c349dbc7Sjsg 	intel_uncore_write(uncore, RCBMINAVG, 80000);
575c349dbc7Sjsg 
576c349dbc7Sjsg 	intel_uncore_write(uncore, MEMIHYST, 1);
577c349dbc7Sjsg 
578c349dbc7Sjsg 	/* Set up min, max, and cur for interrupt handling */
579c349dbc7Sjsg 	fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
580c349dbc7Sjsg 		MEMMODE_FSTART_SHIFT;
581c349dbc7Sjsg 
582c349dbc7Sjsg 	vstart = (intel_uncore_read(uncore, PXVFREQ(fstart)) &
583c349dbc7Sjsg 		  PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT;
584c349dbc7Sjsg 
585c349dbc7Sjsg 	intel_uncore_write(uncore,
586c349dbc7Sjsg 			   MEMINTREN,
587c349dbc7Sjsg 			   MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
588c349dbc7Sjsg 
589c349dbc7Sjsg 	intel_uncore_write(uncore, VIDSTART, vstart);
590c349dbc7Sjsg 	intel_uncore_posting_read(uncore, VIDSTART);
591c349dbc7Sjsg 
592c349dbc7Sjsg 	rgvmodectl |= MEMMODE_SWMODE_EN;
593c349dbc7Sjsg 	intel_uncore_write(uncore, MEMMODECTL, rgvmodectl);
594c349dbc7Sjsg 
595c349dbc7Sjsg 	if (wait_for_atomic((intel_uncore_read(uncore, MEMSWCTL) &
596c349dbc7Sjsg 			     MEMCTL_CMD_STS) == 0, 10))
597ad8b1aafSjsg 		drm_err(&uncore->i915->drm,
598ad8b1aafSjsg 			"stuck trying to change perf mode\n");
599c349dbc7Sjsg 	mdelay(1);
600c349dbc7Sjsg 
6015ca02815Sjsg 	__gen5_rps_set(rps, rps->cur_freq);
602c349dbc7Sjsg 
603c349dbc7Sjsg 	rps->ips.last_count1 = intel_uncore_read(uncore, DMIEC);
604c349dbc7Sjsg 	rps->ips.last_count1 += intel_uncore_read(uncore, DDREC);
605c349dbc7Sjsg 	rps->ips.last_count1 += intel_uncore_read(uncore, CSIEC);
606c349dbc7Sjsg 	rps->ips.last_time1 = jiffies_to_msecs(jiffies);
607c349dbc7Sjsg 
608c349dbc7Sjsg 	rps->ips.last_count2 = intel_uncore_read(uncore, GFXEC);
609c349dbc7Sjsg 	rps->ips.last_time2 = ktime_get_raw_ns();
610c349dbc7Sjsg 
6115ca02815Sjsg 	spin_lock(&i915->irq_lock);
6125ca02815Sjsg 	ilk_enable_display_irq(i915, DE_PCU_EVENT);
6135ca02815Sjsg 	spin_unlock(&i915->irq_lock);
6145ca02815Sjsg 
615c349dbc7Sjsg 	spin_unlock_irq(&mchdev_lock);
616c349dbc7Sjsg 
617c349dbc7Sjsg 	rps->ips.corr = init_emon(uncore);
618c349dbc7Sjsg 
619c349dbc7Sjsg 	return true;
620c349dbc7Sjsg }
621c349dbc7Sjsg 
gen5_rps_disable(struct intel_rps * rps)622c349dbc7Sjsg static void gen5_rps_disable(struct intel_rps *rps)
623c349dbc7Sjsg {
6245ca02815Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
625c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
626c349dbc7Sjsg 	u16 rgvswctl;
627c349dbc7Sjsg 
628c349dbc7Sjsg 	spin_lock_irq(&mchdev_lock);
629c349dbc7Sjsg 
6305ca02815Sjsg 	spin_lock(&i915->irq_lock);
6315ca02815Sjsg 	ilk_disable_display_irq(i915, DE_PCU_EVENT);
6325ca02815Sjsg 	spin_unlock(&i915->irq_lock);
6335ca02815Sjsg 
634c349dbc7Sjsg 	rgvswctl = intel_uncore_read16(uncore, MEMSWCTL);
635c349dbc7Sjsg 
636c349dbc7Sjsg 	/* Ack interrupts, disable EFC interrupt */
637f005ef32Sjsg 	intel_uncore_rmw(uncore, MEMINTREN, MEMINT_EVAL_CHG_EN, 0);
638c349dbc7Sjsg 	intel_uncore_write(uncore, MEMINTRSTS, MEMINT_EVAL_CHG);
639c349dbc7Sjsg 
640c349dbc7Sjsg 	/* Go back to the starting frequency */
6415ca02815Sjsg 	__gen5_rps_set(rps, rps->idle_freq);
642c349dbc7Sjsg 	mdelay(1);
643c349dbc7Sjsg 	rgvswctl |= MEMCTL_CMD_STS;
644c349dbc7Sjsg 	intel_uncore_write(uncore, MEMSWCTL, rgvswctl);
645c349dbc7Sjsg 	mdelay(1);
646c349dbc7Sjsg 
647c349dbc7Sjsg 	spin_unlock_irq(&mchdev_lock);
648c349dbc7Sjsg }
649c349dbc7Sjsg 
rps_limits(struct intel_rps * rps,u8 val)650c349dbc7Sjsg static u32 rps_limits(struct intel_rps *rps, u8 val)
651c349dbc7Sjsg {
652c349dbc7Sjsg 	u32 limits;
653c349dbc7Sjsg 
654c349dbc7Sjsg 	/*
655c349dbc7Sjsg 	 * Only set the down limit when we've reached the lowest level to avoid
656c349dbc7Sjsg 	 * getting more interrupts, otherwise leave this clear. This prevents a
657c349dbc7Sjsg 	 * race in the hw when coming out of rc6: There's a tiny window where
658c349dbc7Sjsg 	 * the hw runs at the minimal clock before selecting the desired
659c349dbc7Sjsg 	 * frequency, if the down threshold expires in that window we will not
660c349dbc7Sjsg 	 * receive a down interrupt.
661c349dbc7Sjsg 	 */
6625ca02815Sjsg 	if (GRAPHICS_VER(rps_to_i915(rps)) >= 9) {
663c349dbc7Sjsg 		limits = rps->max_freq_softlimit << 23;
664c349dbc7Sjsg 		if (val <= rps->min_freq_softlimit)
665c349dbc7Sjsg 			limits |= rps->min_freq_softlimit << 14;
666c349dbc7Sjsg 	} else {
667c349dbc7Sjsg 		limits = rps->max_freq_softlimit << 24;
668c349dbc7Sjsg 		if (val <= rps->min_freq_softlimit)
669c349dbc7Sjsg 			limits |= rps->min_freq_softlimit << 16;
670c349dbc7Sjsg 	}
671c349dbc7Sjsg 
672c349dbc7Sjsg 	return limits;
673c349dbc7Sjsg }
674c349dbc7Sjsg 
rps_set_power(struct intel_rps * rps,int new_power)675c349dbc7Sjsg static void rps_set_power(struct intel_rps *rps, int new_power)
676c349dbc7Sjsg {
677ad8b1aafSjsg 	struct intel_gt *gt = rps_to_gt(rps);
678ad8b1aafSjsg 	struct intel_uncore *uncore = gt->uncore;
679c349dbc7Sjsg 	u32 ei_up = 0, ei_down = 0;
680c349dbc7Sjsg 
681c349dbc7Sjsg 	lockdep_assert_held(&rps->power.mutex);
682c349dbc7Sjsg 
683c349dbc7Sjsg 	if (new_power == rps->power.mode)
684c349dbc7Sjsg 		return;
685c349dbc7Sjsg 
686c349dbc7Sjsg 	/* Note the units here are not exactly 1us, but 1280ns. */
687c349dbc7Sjsg 	switch (new_power) {
688c349dbc7Sjsg 	case LOW_POWER:
689c349dbc7Sjsg 		ei_up = 16000;
690c349dbc7Sjsg 		ei_down = 32000;
691c349dbc7Sjsg 		break;
692c349dbc7Sjsg 
693c349dbc7Sjsg 	case BETWEEN:
694c349dbc7Sjsg 		ei_up = 13000;
695c349dbc7Sjsg 		ei_down = 32000;
696c349dbc7Sjsg 		break;
697c349dbc7Sjsg 
698c349dbc7Sjsg 	case HIGH_POWER:
699c349dbc7Sjsg 		ei_up = 10000;
700c349dbc7Sjsg 		ei_down = 32000;
701c349dbc7Sjsg 		break;
702c349dbc7Sjsg 	}
703c349dbc7Sjsg 
704c349dbc7Sjsg 	/* When byt can survive without system hang with dynamic
705c349dbc7Sjsg 	 * sw freq adjustments, this restriction can be lifted.
706c349dbc7Sjsg 	 */
707ad8b1aafSjsg 	if (IS_VALLEYVIEW(gt->i915))
708c349dbc7Sjsg 		goto skip_hw_write;
709c349dbc7Sjsg 
710ad8b1aafSjsg 	GT_TRACE(gt,
711ad8b1aafSjsg 		 "changing power mode [%d], up %d%% @ %dus, down %d%% @ %dus\n",
712f005ef32Sjsg 		 new_power,
713f005ef32Sjsg 		 rps->power.up_threshold, ei_up,
714f005ef32Sjsg 		 rps->power.down_threshold, ei_down);
715c349dbc7Sjsg 
716ad8b1aafSjsg 	set(uncore, GEN6_RP_UP_EI,
717ad8b1aafSjsg 	    intel_gt_ns_to_pm_interval(gt, ei_up * 1000));
718ad8b1aafSjsg 	set(uncore, GEN6_RP_UP_THRESHOLD,
719f005ef32Sjsg 	    intel_gt_ns_to_pm_interval(gt,
720f005ef32Sjsg 				       ei_up * rps->power.up_threshold * 10));
721ad8b1aafSjsg 
722ad8b1aafSjsg 	set(uncore, GEN6_RP_DOWN_EI,
723ad8b1aafSjsg 	    intel_gt_ns_to_pm_interval(gt, ei_down * 1000));
724c349dbc7Sjsg 	set(uncore, GEN6_RP_DOWN_THRESHOLD,
725f005ef32Sjsg 	    intel_gt_ns_to_pm_interval(gt,
726f005ef32Sjsg 				       ei_down *
727f005ef32Sjsg 				       rps->power.down_threshold * 10));
728c349dbc7Sjsg 
729c349dbc7Sjsg 	set(uncore, GEN6_RP_CONTROL,
7305ca02815Sjsg 	    (GRAPHICS_VER(gt->i915) > 9 ? 0 : GEN6_RP_MEDIA_TURBO) |
731c349dbc7Sjsg 	    GEN6_RP_MEDIA_HW_NORMAL_MODE |
732c349dbc7Sjsg 	    GEN6_RP_MEDIA_IS_GFX |
733c349dbc7Sjsg 	    GEN6_RP_ENABLE |
734c349dbc7Sjsg 	    GEN6_RP_UP_BUSY_AVG |
735c349dbc7Sjsg 	    GEN6_RP_DOWN_IDLE_AVG);
736c349dbc7Sjsg 
737c349dbc7Sjsg skip_hw_write:
738c349dbc7Sjsg 	rps->power.mode = new_power;
739c349dbc7Sjsg }
740c349dbc7Sjsg 
gen6_rps_set_thresholds(struct intel_rps * rps,u8 val)741c349dbc7Sjsg static void gen6_rps_set_thresholds(struct intel_rps *rps, u8 val)
742c349dbc7Sjsg {
743c349dbc7Sjsg 	int new_power;
744c349dbc7Sjsg 
745c349dbc7Sjsg 	new_power = rps->power.mode;
746c349dbc7Sjsg 	switch (rps->power.mode) {
747c349dbc7Sjsg 	case LOW_POWER:
748c349dbc7Sjsg 		if (val > rps->efficient_freq + 1 &&
749c349dbc7Sjsg 		    val > rps->cur_freq)
750c349dbc7Sjsg 			new_power = BETWEEN;
751c349dbc7Sjsg 		break;
752c349dbc7Sjsg 
753c349dbc7Sjsg 	case BETWEEN:
754c349dbc7Sjsg 		if (val <= rps->efficient_freq &&
755c349dbc7Sjsg 		    val < rps->cur_freq)
756c349dbc7Sjsg 			new_power = LOW_POWER;
757c349dbc7Sjsg 		else if (val >= rps->rp0_freq &&
758c349dbc7Sjsg 			 val > rps->cur_freq)
759c349dbc7Sjsg 			new_power = HIGH_POWER;
760c349dbc7Sjsg 		break;
761c349dbc7Sjsg 
762c349dbc7Sjsg 	case HIGH_POWER:
763c349dbc7Sjsg 		if (val < (rps->rp1_freq + rps->rp0_freq) >> 1 &&
764c349dbc7Sjsg 		    val < rps->cur_freq)
765c349dbc7Sjsg 			new_power = BETWEEN;
766c349dbc7Sjsg 		break;
767c349dbc7Sjsg 	}
768c349dbc7Sjsg 	/* Max/min bins are special */
769c349dbc7Sjsg 	if (val <= rps->min_freq_softlimit)
770c349dbc7Sjsg 		new_power = LOW_POWER;
771c349dbc7Sjsg 	if (val >= rps->max_freq_softlimit)
772c349dbc7Sjsg 		new_power = HIGH_POWER;
773c349dbc7Sjsg 
774c349dbc7Sjsg 	mutex_lock(&rps->power.mutex);
775c349dbc7Sjsg 	if (rps->power.interactive)
776c349dbc7Sjsg 		new_power = HIGH_POWER;
777c349dbc7Sjsg 	rps_set_power(rps, new_power);
778c349dbc7Sjsg 	mutex_unlock(&rps->power.mutex);
779c349dbc7Sjsg }
780c349dbc7Sjsg 
intel_rps_mark_interactive(struct intel_rps * rps,bool interactive)781c349dbc7Sjsg void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive)
782c349dbc7Sjsg {
7831bb76ff1Sjsg 	GT_TRACE(rps_to_gt(rps), "mark interactive: %s\n",
7841bb76ff1Sjsg 		 str_yes_no(interactive));
785ad8b1aafSjsg 
786c349dbc7Sjsg 	mutex_lock(&rps->power.mutex);
787c349dbc7Sjsg 	if (interactive) {
788ad8b1aafSjsg 		if (!rps->power.interactive++ && intel_rps_is_active(rps))
789c349dbc7Sjsg 			rps_set_power(rps, HIGH_POWER);
790c349dbc7Sjsg 	} else {
791c349dbc7Sjsg 		GEM_BUG_ON(!rps->power.interactive);
792c349dbc7Sjsg 		rps->power.interactive--;
793c349dbc7Sjsg 	}
794c349dbc7Sjsg 	mutex_unlock(&rps->power.mutex);
795c349dbc7Sjsg }
796c349dbc7Sjsg 
gen6_rps_set(struct intel_rps * rps,u8 val)797c349dbc7Sjsg static int gen6_rps_set(struct intel_rps *rps, u8 val)
798c349dbc7Sjsg {
799c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
800c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
801c349dbc7Sjsg 	u32 swreq;
802c349dbc7Sjsg 
8035ca02815Sjsg 	GEM_BUG_ON(rps_uses_slpc(rps));
8045ca02815Sjsg 
8055ca02815Sjsg 	if (GRAPHICS_VER(i915) >= 9)
806c349dbc7Sjsg 		swreq = GEN9_FREQUENCY(val);
807c349dbc7Sjsg 	else if (IS_HASWELL(i915) || IS_BROADWELL(i915))
808c349dbc7Sjsg 		swreq = HSW_FREQUENCY(val);
809c349dbc7Sjsg 	else
810c349dbc7Sjsg 		swreq = (GEN6_FREQUENCY(val) |
811c349dbc7Sjsg 			 GEN6_OFFSET(0) |
812c349dbc7Sjsg 			 GEN6_AGGRESSIVE_TURBO);
813c349dbc7Sjsg 	set(uncore, GEN6_RPNSWREQ, swreq);
814c349dbc7Sjsg 
815ad8b1aafSjsg 	GT_TRACE(rps_to_gt(rps), "set val:%x, freq:%d, swreq:%x\n",
816ad8b1aafSjsg 		 val, intel_gpu_freq(rps, val), swreq);
817ad8b1aafSjsg 
818c349dbc7Sjsg 	return 0;
819c349dbc7Sjsg }
820c349dbc7Sjsg 
vlv_rps_set(struct intel_rps * rps,u8 val)821c349dbc7Sjsg static int vlv_rps_set(struct intel_rps *rps, u8 val)
822c349dbc7Sjsg {
823c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
824c349dbc7Sjsg 	int err;
825c349dbc7Sjsg 
826c349dbc7Sjsg 	vlv_punit_get(i915);
827c349dbc7Sjsg 	err = vlv_punit_write(i915, PUNIT_REG_GPU_FREQ_REQ, val);
828c349dbc7Sjsg 	vlv_punit_put(i915);
829c349dbc7Sjsg 
830ad8b1aafSjsg 	GT_TRACE(rps_to_gt(rps), "set val:%x, freq:%d\n",
831ad8b1aafSjsg 		 val, intel_gpu_freq(rps, val));
832ad8b1aafSjsg 
833c349dbc7Sjsg 	return err;
834c349dbc7Sjsg }
835c349dbc7Sjsg 
rps_set(struct intel_rps * rps,u8 val,bool update)836c349dbc7Sjsg static int rps_set(struct intel_rps *rps, u8 val, bool update)
837c349dbc7Sjsg {
838c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
839c349dbc7Sjsg 	int err;
840c349dbc7Sjsg 
841c349dbc7Sjsg 	if (val == rps->last_freq)
842c349dbc7Sjsg 		return 0;
843c349dbc7Sjsg 
844c349dbc7Sjsg 	if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
845c349dbc7Sjsg 		err = vlv_rps_set(rps, val);
8465ca02815Sjsg 	else if (GRAPHICS_VER(i915) >= 6)
847c349dbc7Sjsg 		err = gen6_rps_set(rps, val);
8485ca02815Sjsg 	else
8495ca02815Sjsg 		err = gen5_rps_set(rps, val);
850c349dbc7Sjsg 	if (err)
851c349dbc7Sjsg 		return err;
852c349dbc7Sjsg 
8535ca02815Sjsg 	if (update && GRAPHICS_VER(i915) >= 6)
854c349dbc7Sjsg 		gen6_rps_set_thresholds(rps, val);
855c349dbc7Sjsg 	rps->last_freq = val;
856c349dbc7Sjsg 
857c349dbc7Sjsg 	return 0;
858c349dbc7Sjsg }
859c349dbc7Sjsg 
intel_rps_unpark(struct intel_rps * rps)860c349dbc7Sjsg void intel_rps_unpark(struct intel_rps *rps)
861c349dbc7Sjsg {
862ad8b1aafSjsg 	if (!intel_rps_is_enabled(rps))
863c349dbc7Sjsg 		return;
864c349dbc7Sjsg 
865ad8b1aafSjsg 	GT_TRACE(rps_to_gt(rps), "unpark:%x\n", rps->cur_freq);
866ad8b1aafSjsg 
867c349dbc7Sjsg 	/*
868c349dbc7Sjsg 	 * Use the user's desired frequency as a guide, but for better
869c349dbc7Sjsg 	 * performance, jump directly to RPe as our starting frequency.
870c349dbc7Sjsg 	 */
871c349dbc7Sjsg 	mutex_lock(&rps->lock);
872c349dbc7Sjsg 
873ad8b1aafSjsg 	intel_rps_set_active(rps);
874ad8b1aafSjsg 	intel_rps_set(rps,
875ad8b1aafSjsg 		      clamp(rps->cur_freq,
876ad8b1aafSjsg 			    rps->min_freq_softlimit,
877ad8b1aafSjsg 			    rps->max_freq_softlimit));
878c349dbc7Sjsg 
879c349dbc7Sjsg 	mutex_unlock(&rps->lock);
880c349dbc7Sjsg 
881ad8b1aafSjsg 	rps->pm_iir = 0;
882ad8b1aafSjsg 	if (intel_rps_has_interrupts(rps))
883c349dbc7Sjsg 		rps_enable_interrupts(rps);
884ad8b1aafSjsg 	if (intel_rps_uses_timer(rps))
885ad8b1aafSjsg 		rps_start_timer(rps);
886c349dbc7Sjsg 
8875ca02815Sjsg 	if (GRAPHICS_VER(rps_to_i915(rps)) == 5)
888c349dbc7Sjsg 		gen5_rps_update(rps);
889c349dbc7Sjsg }
890c349dbc7Sjsg 
intel_rps_park(struct intel_rps * rps)891c349dbc7Sjsg void intel_rps_park(struct intel_rps *rps)
892c349dbc7Sjsg {
893ad8b1aafSjsg 	int adj;
894c349dbc7Sjsg 
8955ca02815Sjsg 	if (!intel_rps_is_enabled(rps))
8965ca02815Sjsg 		return;
8975ca02815Sjsg 
898ad8b1aafSjsg 	if (!intel_rps_clear_active(rps))
899c349dbc7Sjsg 		return;
900c349dbc7Sjsg 
901ad8b1aafSjsg 	if (intel_rps_uses_timer(rps))
902ad8b1aafSjsg 		rps_stop_timer(rps);
903ad8b1aafSjsg 	if (intel_rps_has_interrupts(rps))
904c349dbc7Sjsg 		rps_disable_interrupts(rps);
905c349dbc7Sjsg 
906c349dbc7Sjsg 	if (rps->last_freq <= rps->idle_freq)
907c349dbc7Sjsg 		return;
908c349dbc7Sjsg 
909c349dbc7Sjsg 	/*
910c349dbc7Sjsg 	 * The punit delays the write of the frequency and voltage until it
911c349dbc7Sjsg 	 * determines the GPU is awake. During normal usage we don't want to
912c349dbc7Sjsg 	 * waste power changing the frequency if the GPU is sleeping (rc6).
913c349dbc7Sjsg 	 * However, the GPU and driver is now idle and we do not want to delay
914c349dbc7Sjsg 	 * switching to minimum voltage (reducing power whilst idle) as we do
915c349dbc7Sjsg 	 * not expect to be woken in the near future and so must flush the
916c349dbc7Sjsg 	 * change by waking the device.
917c349dbc7Sjsg 	 *
918c349dbc7Sjsg 	 * We choose to take the media powerwell (either would do to trick the
919c349dbc7Sjsg 	 * punit into committing the voltage change) as that takes a lot less
920c349dbc7Sjsg 	 * power than the render powerwell.
921c349dbc7Sjsg 	 */
922c349dbc7Sjsg 	intel_uncore_forcewake_get(rps_to_uncore(rps), FORCEWAKE_MEDIA);
923c349dbc7Sjsg 	rps_set(rps, rps->idle_freq, false);
924c349dbc7Sjsg 	intel_uncore_forcewake_put(rps_to_uncore(rps), FORCEWAKE_MEDIA);
925c349dbc7Sjsg 
926c349dbc7Sjsg 	/*
927c349dbc7Sjsg 	 * Since we will try and restart from the previously requested
928c349dbc7Sjsg 	 * frequency on unparking, treat this idle point as a downclock
929c349dbc7Sjsg 	 * interrupt and reduce the frequency for resume. If we park/unpark
930c349dbc7Sjsg 	 * more frequently than the rps worker can run, we will not respond
931c349dbc7Sjsg 	 * to any EI and never see a change in frequency.
932c349dbc7Sjsg 	 *
933c349dbc7Sjsg 	 * (Note we accommodate Cherryview's limitation of only using an
934c349dbc7Sjsg 	 * even bin by applying it to all.)
935c349dbc7Sjsg 	 */
936ad8b1aafSjsg 	adj = rps->last_adj;
937ad8b1aafSjsg 	if (adj < 0)
938ad8b1aafSjsg 		adj *= 2;
939ad8b1aafSjsg 	else /* CHV needs even encode values */
940ad8b1aafSjsg 		adj = -2;
941ad8b1aafSjsg 	rps->last_adj = adj;
942ad8b1aafSjsg 	rps->cur_freq = max_t(int, rps->cur_freq + adj, rps->min_freq);
943ad8b1aafSjsg 	if (rps->cur_freq < rps->efficient_freq) {
944ad8b1aafSjsg 		rps->cur_freq = rps->efficient_freq;
945ad8b1aafSjsg 		rps->last_adj = 0;
946ad8b1aafSjsg 	}
947ad8b1aafSjsg 
948ad8b1aafSjsg 	GT_TRACE(rps_to_gt(rps), "park:%x\n", rps->cur_freq);
949c349dbc7Sjsg }
950c349dbc7Sjsg 
intel_rps_get_boost_frequency(struct intel_rps * rps)9511bb76ff1Sjsg u32 intel_rps_get_boost_frequency(struct intel_rps *rps)
9521bb76ff1Sjsg {
9531bb76ff1Sjsg 	struct intel_guc_slpc *slpc;
9541bb76ff1Sjsg 
9551bb76ff1Sjsg 	if (rps_uses_slpc(rps)) {
9561bb76ff1Sjsg 		slpc = rps_to_slpc(rps);
9571bb76ff1Sjsg 
9581bb76ff1Sjsg 		return slpc->boost_freq;
9591bb76ff1Sjsg 	} else {
9601bb76ff1Sjsg 		return intel_gpu_freq(rps, rps->boost_freq);
9611bb76ff1Sjsg 	}
9621bb76ff1Sjsg }
9631bb76ff1Sjsg 
rps_set_boost_freq(struct intel_rps * rps,u32 val)9641bb76ff1Sjsg static int rps_set_boost_freq(struct intel_rps *rps, u32 val)
9651bb76ff1Sjsg {
9661bb76ff1Sjsg 	bool boost = false;
9671bb76ff1Sjsg 
9681bb76ff1Sjsg 	/* Validate against (static) hardware limits */
9691bb76ff1Sjsg 	val = intel_freq_opcode(rps, val);
9701bb76ff1Sjsg 	if (val < rps->min_freq || val > rps->max_freq)
9711bb76ff1Sjsg 		return -EINVAL;
9721bb76ff1Sjsg 
9731bb76ff1Sjsg 	mutex_lock(&rps->lock);
9741bb76ff1Sjsg 	if (val != rps->boost_freq) {
9751bb76ff1Sjsg 		rps->boost_freq = val;
9761bb76ff1Sjsg 		boost = atomic_read(&rps->num_waiters);
9771bb76ff1Sjsg 	}
9781bb76ff1Sjsg 	mutex_unlock(&rps->lock);
9791bb76ff1Sjsg 	if (boost)
980f005ef32Sjsg 		queue_work(rps_to_gt(rps)->i915->unordered_wq, &rps->work);
9811bb76ff1Sjsg 
9821bb76ff1Sjsg 	return 0;
9831bb76ff1Sjsg }
9841bb76ff1Sjsg 
intel_rps_set_boost_frequency(struct intel_rps * rps,u32 freq)9851bb76ff1Sjsg int intel_rps_set_boost_frequency(struct intel_rps *rps, u32 freq)
9861bb76ff1Sjsg {
9871bb76ff1Sjsg 	struct intel_guc_slpc *slpc;
9881bb76ff1Sjsg 
9891bb76ff1Sjsg 	if (rps_uses_slpc(rps)) {
9901bb76ff1Sjsg 		slpc = rps_to_slpc(rps);
9911bb76ff1Sjsg 
9921bb76ff1Sjsg 		return intel_guc_slpc_set_boost_freq(slpc, freq);
9931bb76ff1Sjsg 	} else {
9941bb76ff1Sjsg 		return rps_set_boost_freq(rps, freq);
9951bb76ff1Sjsg 	}
9961bb76ff1Sjsg }
9971bb76ff1Sjsg 
intel_rps_dec_waiters(struct intel_rps * rps)9981bb76ff1Sjsg void intel_rps_dec_waiters(struct intel_rps *rps)
9991bb76ff1Sjsg {
10001bb76ff1Sjsg 	struct intel_guc_slpc *slpc;
10011bb76ff1Sjsg 
10021bb76ff1Sjsg 	if (rps_uses_slpc(rps)) {
10031bb76ff1Sjsg 		slpc = rps_to_slpc(rps);
10041bb76ff1Sjsg 
10051bb76ff1Sjsg 		intel_guc_slpc_dec_waiters(slpc);
10061bb76ff1Sjsg 	} else {
10071bb76ff1Sjsg 		atomic_dec(&rps->num_waiters);
10081bb76ff1Sjsg 	}
10091bb76ff1Sjsg }
10101bb76ff1Sjsg 
intel_rps_boost(struct i915_request * rq)1011c349dbc7Sjsg void intel_rps_boost(struct i915_request *rq)
1012c349dbc7Sjsg {
10131bb76ff1Sjsg 	struct intel_guc_slpc *slpc;
10141bb76ff1Sjsg 
10155ca02815Sjsg 	if (i915_request_signaled(rq) || i915_request_has_waitboost(rq))
1016c349dbc7Sjsg 		return;
1017c349dbc7Sjsg 
1018c349dbc7Sjsg 	/* Serializes with i915_request_retire() */
10195ca02815Sjsg 	if (!test_and_set_bit(I915_FENCE_FLAG_BOOST, &rq->fence.flags)) {
10205ca02815Sjsg 		struct intel_rps *rps = &READ_ONCE(rq->engine)->gt->rps;
10215ca02815Sjsg 
10221bb76ff1Sjsg 		if (rps_uses_slpc(rps)) {
10231bb76ff1Sjsg 			slpc = rps_to_slpc(rps);
10241bb76ff1Sjsg 
1025f005ef32Sjsg 			if (slpc->min_freq_softlimit >= slpc->boost_freq)
1026f005ef32Sjsg 				return;
1027f005ef32Sjsg 
10281bb76ff1Sjsg 			/* Return if old value is non zero */
1029f005ef32Sjsg 			if (!atomic_fetch_inc(&slpc->num_waiters)) {
1030f005ef32Sjsg 				GT_TRACE(rps_to_gt(rps), "boost fence:%llx:%llx\n",
1031f005ef32Sjsg 					 rq->fence.context, rq->fence.seqno);
1032f005ef32Sjsg 				queue_work(rps_to_gt(rps)->i915->unordered_wq,
1033f005ef32Sjsg 					   &slpc->boost_work);
1034f005ef32Sjsg 			}
10351bb76ff1Sjsg 
10361bb76ff1Sjsg 			return;
10371bb76ff1Sjsg 		}
10381bb76ff1Sjsg 
10395ca02815Sjsg 		if (atomic_fetch_inc(&rps->num_waiters))
10405ca02815Sjsg 			return;
10415ca02815Sjsg 
10425ca02815Sjsg 		if (!intel_rps_is_active(rps))
10435ca02815Sjsg 			return;
1044c349dbc7Sjsg 
1045ad8b1aafSjsg 		GT_TRACE(rps_to_gt(rps), "boost fence:%llx:%llx\n",
1046ad8b1aafSjsg 			 rq->fence.context, rq->fence.seqno);
1047ad8b1aafSjsg 
10485ca02815Sjsg 		if (READ_ONCE(rps->cur_freq) < rps->boost_freq)
1049f005ef32Sjsg 			queue_work(rps_to_gt(rps)->i915->unordered_wq, &rps->work);
1050c349dbc7Sjsg 
10515ca02815Sjsg 		WRITE_ONCE(rps->boosts, rps->boosts + 1); /* debug only */
1052c349dbc7Sjsg 	}
1053c349dbc7Sjsg }
1054c349dbc7Sjsg 
intel_rps_set(struct intel_rps * rps,u8 val)1055c349dbc7Sjsg int intel_rps_set(struct intel_rps *rps, u8 val)
1056c349dbc7Sjsg {
1057c349dbc7Sjsg 	int err;
1058c349dbc7Sjsg 
1059c349dbc7Sjsg 	lockdep_assert_held(&rps->lock);
1060c349dbc7Sjsg 	GEM_BUG_ON(val > rps->max_freq);
1061c349dbc7Sjsg 	GEM_BUG_ON(val < rps->min_freq);
1062c349dbc7Sjsg 
1063ad8b1aafSjsg 	if (intel_rps_is_active(rps)) {
1064c349dbc7Sjsg 		err = rps_set(rps, val, true);
1065c349dbc7Sjsg 		if (err)
1066c349dbc7Sjsg 			return err;
1067c349dbc7Sjsg 
1068c349dbc7Sjsg 		/*
1069c349dbc7Sjsg 		 * Make sure we continue to get interrupts
1070c349dbc7Sjsg 		 * until we hit the minimum or maximum frequencies.
1071c349dbc7Sjsg 		 */
1072ad8b1aafSjsg 		if (intel_rps_has_interrupts(rps)) {
1073c349dbc7Sjsg 			struct intel_uncore *uncore = rps_to_uncore(rps);
1074c349dbc7Sjsg 
1075c349dbc7Sjsg 			set(uncore,
1076c349dbc7Sjsg 			    GEN6_RP_INTERRUPT_LIMITS, rps_limits(rps, val));
1077c349dbc7Sjsg 
1078c349dbc7Sjsg 			set(uncore, GEN6_PMINTRMSK, rps_pm_mask(rps, val));
1079c349dbc7Sjsg 		}
1080c349dbc7Sjsg 	}
1081c349dbc7Sjsg 
1082c349dbc7Sjsg 	rps->cur_freq = val;
1083c349dbc7Sjsg 	return 0;
1084c349dbc7Sjsg }
1085c349dbc7Sjsg 
intel_rps_read_state_cap(struct intel_rps * rps)10861bb76ff1Sjsg static u32 intel_rps_read_state_cap(struct intel_rps *rps)
1087c349dbc7Sjsg {
1088c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1089c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
1090c349dbc7Sjsg 
10911bb76ff1Sjsg 	if (IS_PONTEVECCHIO(i915))
10921bb76ff1Sjsg 		return intel_uncore_read(uncore, PVC_RP_STATE_CAP);
10931bb76ff1Sjsg 	else if (IS_XEHPSDV(i915))
10941bb76ff1Sjsg 		return intel_uncore_read(uncore, XEHPSDV_RP_STATE_CAP);
10951bb76ff1Sjsg 	else if (IS_GEN9_LP(i915))
10961bb76ff1Sjsg 		return intel_uncore_read(uncore, BXT_RP_STATE_CAP);
10971bb76ff1Sjsg 	else
10981bb76ff1Sjsg 		return intel_uncore_read(uncore, GEN6_RP_STATE_CAP);
10991bb76ff1Sjsg }
11001bb76ff1Sjsg 
1101f005ef32Sjsg static void
mtl_get_freq_caps(struct intel_rps * rps,struct intel_rps_freq_caps * caps)1102f005ef32Sjsg mtl_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps)
1103f005ef32Sjsg {
1104f005ef32Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
1105f005ef32Sjsg 	u32 rp_state_cap = rps_to_gt(rps)->type == GT_MEDIA ?
1106f005ef32Sjsg 				intel_uncore_read(uncore, MTL_MEDIAP_STATE_CAP) :
1107f005ef32Sjsg 				intel_uncore_read(uncore, MTL_RP_STATE_CAP);
1108f005ef32Sjsg 	u32 rpe = rps_to_gt(rps)->type == GT_MEDIA ?
1109f005ef32Sjsg 			intel_uncore_read(uncore, MTL_MPE_FREQUENCY) :
1110f005ef32Sjsg 			intel_uncore_read(uncore, MTL_GT_RPE_FREQUENCY);
1111f005ef32Sjsg 
1112f005ef32Sjsg 	/* MTL values are in units of 16.67 MHz */
1113f005ef32Sjsg 	caps->rp0_freq = REG_FIELD_GET(MTL_RP0_CAP_MASK, rp_state_cap);
1114f005ef32Sjsg 	caps->min_freq = REG_FIELD_GET(MTL_RPN_CAP_MASK, rp_state_cap);
1115f005ef32Sjsg 	caps->rp1_freq = REG_FIELD_GET(MTL_RPE_MASK, rpe);
1116f005ef32Sjsg }
1117f005ef32Sjsg 
1118f005ef32Sjsg static void
__gen6_rps_get_freq_caps(struct intel_rps * rps,struct intel_rps_freq_caps * caps)1119f005ef32Sjsg __gen6_rps_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps)
11201bb76ff1Sjsg {
11211bb76ff1Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
11221bb76ff1Sjsg 	u32 rp_state_cap;
11231bb76ff1Sjsg 
11241bb76ff1Sjsg 	rp_state_cap = intel_rps_read_state_cap(rps);
1125c349dbc7Sjsg 
1126c349dbc7Sjsg 	/* static values from HW: RP0 > RP1 > RPn (min_freq) */
1127c349dbc7Sjsg 	if (IS_GEN9_LP(i915)) {
11281bb76ff1Sjsg 		caps->rp0_freq = (rp_state_cap >> 16) & 0xff;
11291bb76ff1Sjsg 		caps->rp1_freq = (rp_state_cap >>  8) & 0xff;
11301bb76ff1Sjsg 		caps->min_freq = (rp_state_cap >>  0) & 0xff;
1131c349dbc7Sjsg 	} else {
11321bb76ff1Sjsg 		caps->rp0_freq = (rp_state_cap >>  0) & 0xff;
11331bb76ff1Sjsg 		if (GRAPHICS_VER(i915) >= 10)
11341bb76ff1Sjsg 			caps->rp1_freq = REG_FIELD_GET(RPE_MASK,
11351bb76ff1Sjsg 						       intel_uncore_read(to_gt(i915)->uncore,
11361bb76ff1Sjsg 						       GEN10_FREQ_INFO_REC));
11371bb76ff1Sjsg 		else
11381bb76ff1Sjsg 			caps->rp1_freq = (rp_state_cap >>  8) & 0xff;
11391bb76ff1Sjsg 		caps->min_freq = (rp_state_cap >> 16) & 0xff;
1140c349dbc7Sjsg 	}
1141c349dbc7Sjsg 
11421bb76ff1Sjsg 	if (IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 11) {
11431bb76ff1Sjsg 		/*
11441bb76ff1Sjsg 		 * In this case rp_state_cap register reports frequencies in
11451bb76ff1Sjsg 		 * units of 50 MHz. Convert these to the actual "hw unit", i.e.
11461bb76ff1Sjsg 		 * units of 16.67 MHz
11471bb76ff1Sjsg 		 */
11481bb76ff1Sjsg 		caps->rp0_freq *= GEN9_FREQ_SCALER;
11491bb76ff1Sjsg 		caps->rp1_freq *= GEN9_FREQ_SCALER;
11501bb76ff1Sjsg 		caps->min_freq *= GEN9_FREQ_SCALER;
11511bb76ff1Sjsg 	}
11521bb76ff1Sjsg }
11531bb76ff1Sjsg 
1154f005ef32Sjsg /**
1155f005ef32Sjsg  * gen6_rps_get_freq_caps - Get freq caps exposed by HW
1156f005ef32Sjsg  * @rps: the intel_rps structure
1157f005ef32Sjsg  * @caps: returned freq caps
1158f005ef32Sjsg  *
1159f005ef32Sjsg  * Returned "caps" frequencies should be converted to MHz using
1160f005ef32Sjsg  * intel_gpu_freq()
1161f005ef32Sjsg  */
gen6_rps_get_freq_caps(struct intel_rps * rps,struct intel_rps_freq_caps * caps)1162f005ef32Sjsg void gen6_rps_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps)
1163f005ef32Sjsg {
1164f005ef32Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1165f005ef32Sjsg 
1166*ddf58b8fSjsg 	if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
1167f005ef32Sjsg 		return mtl_get_freq_caps(rps, caps);
1168f005ef32Sjsg 	else
1169f005ef32Sjsg 		return __gen6_rps_get_freq_caps(rps, caps);
1170f005ef32Sjsg }
1171f005ef32Sjsg 
gen6_rps_init(struct intel_rps * rps)11721bb76ff1Sjsg static void gen6_rps_init(struct intel_rps *rps)
11731bb76ff1Sjsg {
11741bb76ff1Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
11751bb76ff1Sjsg 	struct intel_rps_freq_caps caps;
11761bb76ff1Sjsg 
11771bb76ff1Sjsg 	gen6_rps_get_freq_caps(rps, &caps);
11781bb76ff1Sjsg 	rps->rp0_freq = caps.rp0_freq;
11791bb76ff1Sjsg 	rps->rp1_freq = caps.rp1_freq;
11801bb76ff1Sjsg 	rps->min_freq = caps.min_freq;
11811bb76ff1Sjsg 
1182c349dbc7Sjsg 	/* hw_max = RP0 until we check for overclocking */
1183c349dbc7Sjsg 	rps->max_freq = rps->rp0_freq;
1184c349dbc7Sjsg 
1185c349dbc7Sjsg 	rps->efficient_freq = rps->rp1_freq;
1186c349dbc7Sjsg 	if (IS_HASWELL(i915) || IS_BROADWELL(i915) ||
11875ca02815Sjsg 	    IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 11) {
1188c349dbc7Sjsg 		u32 ddcc_status = 0;
11891bb76ff1Sjsg 		u32 mult = 1;
1190c349dbc7Sjsg 
11911bb76ff1Sjsg 		if (IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 11)
11921bb76ff1Sjsg 			mult = GEN9_FREQ_SCALER;
11931bb76ff1Sjsg 		if (snb_pcode_read(rps_to_gt(rps)->uncore,
1194c349dbc7Sjsg 				   HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL,
1195c349dbc7Sjsg 				   &ddcc_status, NULL) == 0)
1196c349dbc7Sjsg 			rps->efficient_freq =
11971bb76ff1Sjsg 				clamp_t(u32,
11981bb76ff1Sjsg 					((ddcc_status >> 8) & 0xff) * mult,
1199c349dbc7Sjsg 					rps->min_freq,
1200c349dbc7Sjsg 					rps->max_freq);
1201c349dbc7Sjsg 	}
1202c349dbc7Sjsg }
1203c349dbc7Sjsg 
rps_reset(struct intel_rps * rps)1204c349dbc7Sjsg static bool rps_reset(struct intel_rps *rps)
1205c349dbc7Sjsg {
1206ad8b1aafSjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1207ad8b1aafSjsg 
1208c349dbc7Sjsg 	/* force a reset */
1209c349dbc7Sjsg 	rps->power.mode = -1;
1210c349dbc7Sjsg 	rps->last_freq = -1;
1211c349dbc7Sjsg 
1212c349dbc7Sjsg 	if (rps_set(rps, rps->min_freq, true)) {
1213ad8b1aafSjsg 		drm_err(&i915->drm, "Failed to reset RPS to initial values\n");
1214c349dbc7Sjsg 		return false;
1215c349dbc7Sjsg 	}
1216c349dbc7Sjsg 
1217c349dbc7Sjsg 	rps->cur_freq = rps->min_freq;
1218c349dbc7Sjsg 	return true;
1219c349dbc7Sjsg }
1220c349dbc7Sjsg 
1221c349dbc7Sjsg /* See the Gen9_GT_PM_Programming_Guide doc for the below */
gen9_rps_enable(struct intel_rps * rps)1222c349dbc7Sjsg static bool gen9_rps_enable(struct intel_rps *rps)
1223c349dbc7Sjsg {
1224ad8b1aafSjsg 	struct intel_gt *gt = rps_to_gt(rps);
1225ad8b1aafSjsg 	struct intel_uncore *uncore = gt->uncore;
1226c349dbc7Sjsg 
1227c349dbc7Sjsg 	/* Program defaults and thresholds for RPS */
12285ca02815Sjsg 	if (GRAPHICS_VER(gt->i915) == 9)
1229c349dbc7Sjsg 		intel_uncore_write_fw(uncore, GEN6_RC_VIDEO_FREQ,
1230c349dbc7Sjsg 				      GEN9_FREQUENCY(rps->rp1_freq));
1231c349dbc7Sjsg 
1232c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_IDLE_HYSTERSIS, 0xa);
1233c349dbc7Sjsg 
1234ad8b1aafSjsg 	rps->pm_events = GEN6_PM_RP_UP_THRESHOLD | GEN6_PM_RP_DOWN_THRESHOLD;
1235ad8b1aafSjsg 
1236c349dbc7Sjsg 	return rps_reset(rps);
1237c349dbc7Sjsg }
1238c349dbc7Sjsg 
gen8_rps_enable(struct intel_rps * rps)1239c349dbc7Sjsg static bool gen8_rps_enable(struct intel_rps *rps)
1240c349dbc7Sjsg {
1241c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
1242c349dbc7Sjsg 
1243c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RC_VIDEO_FREQ,
1244c349dbc7Sjsg 			      HSW_FREQUENCY(rps->rp1_freq));
1245c349dbc7Sjsg 
1246c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_IDLE_HYSTERSIS, 10);
1247c349dbc7Sjsg 
1248ad8b1aafSjsg 	rps->pm_events = GEN6_PM_RP_UP_THRESHOLD | GEN6_PM_RP_DOWN_THRESHOLD;
1249ad8b1aafSjsg 
1250c349dbc7Sjsg 	return rps_reset(rps);
1251c349dbc7Sjsg }
1252c349dbc7Sjsg 
gen6_rps_enable(struct intel_rps * rps)1253c349dbc7Sjsg static bool gen6_rps_enable(struct intel_rps *rps)
1254c349dbc7Sjsg {
1255c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
1256c349dbc7Sjsg 
1257c349dbc7Sjsg 	/* Power down if completely idle for over 50ms */
1258c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_DOWN_TIMEOUT, 50000);
1259c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_IDLE_HYSTERSIS, 10);
1260c349dbc7Sjsg 
1261ad8b1aafSjsg 	rps->pm_events = (GEN6_PM_RP_UP_THRESHOLD |
1262ad8b1aafSjsg 			  GEN6_PM_RP_DOWN_THRESHOLD |
1263ad8b1aafSjsg 			  GEN6_PM_RP_DOWN_TIMEOUT);
1264ad8b1aafSjsg 
1265c349dbc7Sjsg 	return rps_reset(rps);
1266c349dbc7Sjsg }
1267c349dbc7Sjsg 
chv_rps_max_freq(struct intel_rps * rps)1268c349dbc7Sjsg static int chv_rps_max_freq(struct intel_rps *rps)
1269c349dbc7Sjsg {
1270c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1271ad8b1aafSjsg 	struct intel_gt *gt = rps_to_gt(rps);
1272c349dbc7Sjsg 	u32 val;
1273c349dbc7Sjsg 
1274c349dbc7Sjsg 	val = vlv_punit_read(i915, FB_GFX_FMAX_AT_VMAX_FUSE);
1275c349dbc7Sjsg 
1276ad8b1aafSjsg 	switch (gt->info.sseu.eu_total) {
1277c349dbc7Sjsg 	case 8:
1278c349dbc7Sjsg 		/* (2 * 4) config */
1279c349dbc7Sjsg 		val >>= FB_GFX_FMAX_AT_VMAX_2SS4EU_FUSE_SHIFT;
1280c349dbc7Sjsg 		break;
1281c349dbc7Sjsg 	case 12:
1282c349dbc7Sjsg 		/* (2 * 6) config */
1283c349dbc7Sjsg 		val >>= FB_GFX_FMAX_AT_VMAX_2SS6EU_FUSE_SHIFT;
1284c349dbc7Sjsg 		break;
1285c349dbc7Sjsg 	case 16:
1286c349dbc7Sjsg 		/* (2 * 8) config */
1287c349dbc7Sjsg 	default:
1288c349dbc7Sjsg 		/* Setting (2 * 8) Min RP0 for any other combination */
1289c349dbc7Sjsg 		val >>= FB_GFX_FMAX_AT_VMAX_2SS8EU_FUSE_SHIFT;
1290c349dbc7Sjsg 		break;
1291c349dbc7Sjsg 	}
1292c349dbc7Sjsg 
1293c349dbc7Sjsg 	return val & FB_GFX_FREQ_FUSE_MASK;
1294c349dbc7Sjsg }
1295c349dbc7Sjsg 
chv_rps_rpe_freq(struct intel_rps * rps)1296c349dbc7Sjsg static int chv_rps_rpe_freq(struct intel_rps *rps)
1297c349dbc7Sjsg {
1298c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1299c349dbc7Sjsg 	u32 val;
1300c349dbc7Sjsg 
1301c349dbc7Sjsg 	val = vlv_punit_read(i915, PUNIT_GPU_DUTYCYCLE_REG);
1302c349dbc7Sjsg 	val >>= PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT;
1303c349dbc7Sjsg 
1304c349dbc7Sjsg 	return val & PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK;
1305c349dbc7Sjsg }
1306c349dbc7Sjsg 
chv_rps_guar_freq(struct intel_rps * rps)1307c349dbc7Sjsg static int chv_rps_guar_freq(struct intel_rps *rps)
1308c349dbc7Sjsg {
1309c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1310c349dbc7Sjsg 	u32 val;
1311c349dbc7Sjsg 
1312c349dbc7Sjsg 	val = vlv_punit_read(i915, FB_GFX_FMAX_AT_VMAX_FUSE);
1313c349dbc7Sjsg 
1314c349dbc7Sjsg 	return val & FB_GFX_FREQ_FUSE_MASK;
1315c349dbc7Sjsg }
1316c349dbc7Sjsg 
chv_rps_min_freq(struct intel_rps * rps)1317c349dbc7Sjsg static u32 chv_rps_min_freq(struct intel_rps *rps)
1318c349dbc7Sjsg {
1319c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1320c349dbc7Sjsg 	u32 val;
1321c349dbc7Sjsg 
1322c349dbc7Sjsg 	val = vlv_punit_read(i915, FB_GFX_FMIN_AT_VMIN_FUSE);
1323c349dbc7Sjsg 	val >>= FB_GFX_FMIN_AT_VMIN_FUSE_SHIFT;
1324c349dbc7Sjsg 
1325c349dbc7Sjsg 	return val & FB_GFX_FREQ_FUSE_MASK;
1326c349dbc7Sjsg }
1327c349dbc7Sjsg 
chv_rps_enable(struct intel_rps * rps)1328c349dbc7Sjsg static bool chv_rps_enable(struct intel_rps *rps)
1329c349dbc7Sjsg {
1330c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
1331c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1332c349dbc7Sjsg 	u32 val;
1333c349dbc7Sjsg 
1334c349dbc7Sjsg 	/* 1: Program defaults and thresholds for RPS*/
1335c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_DOWN_TIMEOUT, 1000000);
1336c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_UP_THRESHOLD, 59400);
1337c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_DOWN_THRESHOLD, 245000);
1338c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_UP_EI, 66000);
1339c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_DOWN_EI, 350000);
1340c349dbc7Sjsg 
1341c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_IDLE_HYSTERSIS, 10);
1342c349dbc7Sjsg 
1343c349dbc7Sjsg 	/* 2: Enable RPS */
1344c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_CONTROL,
1345c349dbc7Sjsg 			      GEN6_RP_MEDIA_HW_NORMAL_MODE |
1346c349dbc7Sjsg 			      GEN6_RP_MEDIA_IS_GFX |
1347c349dbc7Sjsg 			      GEN6_RP_ENABLE |
1348c349dbc7Sjsg 			      GEN6_RP_UP_BUSY_AVG |
1349c349dbc7Sjsg 			      GEN6_RP_DOWN_IDLE_AVG);
1350c349dbc7Sjsg 
1351ad8b1aafSjsg 	rps->pm_events = (GEN6_PM_RP_UP_THRESHOLD |
1352ad8b1aafSjsg 			  GEN6_PM_RP_DOWN_THRESHOLD |
1353ad8b1aafSjsg 			  GEN6_PM_RP_DOWN_TIMEOUT);
1354ad8b1aafSjsg 
1355c349dbc7Sjsg 	/* Setting Fixed Bias */
1356c349dbc7Sjsg 	vlv_punit_get(i915);
1357c349dbc7Sjsg 
1358c349dbc7Sjsg 	val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | CHV_BIAS_CPU_50_SOC_50;
1359c349dbc7Sjsg 	vlv_punit_write(i915, VLV_TURBO_SOC_OVERRIDE, val);
1360c349dbc7Sjsg 
1361c349dbc7Sjsg 	val = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);
1362c349dbc7Sjsg 
1363c349dbc7Sjsg 	vlv_punit_put(i915);
1364c349dbc7Sjsg 
1365c349dbc7Sjsg 	/* RPS code assumes GPLL is used */
1366c349dbc7Sjsg 	drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0,
1367c349dbc7Sjsg 		      "GPLL not enabled\n");
1368c349dbc7Sjsg 
13691bb76ff1Sjsg 	drm_dbg(&i915->drm, "GPLL enabled? %s\n",
13701bb76ff1Sjsg 		str_yes_no(val & GPLLENABLE));
1371ad8b1aafSjsg 	drm_dbg(&i915->drm, "GPU status: 0x%08x\n", val);
1372c349dbc7Sjsg 
1373c349dbc7Sjsg 	return rps_reset(rps);
1374c349dbc7Sjsg }
1375c349dbc7Sjsg 
vlv_rps_guar_freq(struct intel_rps * rps)1376c349dbc7Sjsg static int vlv_rps_guar_freq(struct intel_rps *rps)
1377c349dbc7Sjsg {
1378c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1379c349dbc7Sjsg 	u32 val, rp1;
1380c349dbc7Sjsg 
1381c349dbc7Sjsg 	val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FREQ_FUSE);
1382c349dbc7Sjsg 
1383c349dbc7Sjsg 	rp1 = val & FB_GFX_FGUARANTEED_FREQ_FUSE_MASK;
1384c349dbc7Sjsg 	rp1 >>= FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT;
1385c349dbc7Sjsg 
1386c349dbc7Sjsg 	return rp1;
1387c349dbc7Sjsg }
1388c349dbc7Sjsg 
vlv_rps_max_freq(struct intel_rps * rps)1389c349dbc7Sjsg static int vlv_rps_max_freq(struct intel_rps *rps)
1390c349dbc7Sjsg {
1391c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1392c349dbc7Sjsg 	u32 val, rp0;
1393c349dbc7Sjsg 
1394c349dbc7Sjsg 	val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FREQ_FUSE);
1395c349dbc7Sjsg 
1396c349dbc7Sjsg 	rp0 = (val & FB_GFX_MAX_FREQ_FUSE_MASK) >> FB_GFX_MAX_FREQ_FUSE_SHIFT;
1397c349dbc7Sjsg 	/* Clamp to max */
1398c349dbc7Sjsg 	rp0 = min_t(u32, rp0, 0xea);
1399c349dbc7Sjsg 
1400c349dbc7Sjsg 	return rp0;
1401c349dbc7Sjsg }
1402c349dbc7Sjsg 
vlv_rps_rpe_freq(struct intel_rps * rps)1403c349dbc7Sjsg static int vlv_rps_rpe_freq(struct intel_rps *rps)
1404c349dbc7Sjsg {
1405c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1406c349dbc7Sjsg 	u32 val, rpe;
1407c349dbc7Sjsg 
1408c349dbc7Sjsg 	val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FMAX_FUSE_LO);
1409c349dbc7Sjsg 	rpe = (val & FB_FMAX_VMIN_FREQ_LO_MASK) >> FB_FMAX_VMIN_FREQ_LO_SHIFT;
1410c349dbc7Sjsg 	val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FMAX_FUSE_HI);
1411c349dbc7Sjsg 	rpe |= (val & FB_FMAX_VMIN_FREQ_HI_MASK) << 5;
1412c349dbc7Sjsg 
1413c349dbc7Sjsg 	return rpe;
1414c349dbc7Sjsg }
1415c349dbc7Sjsg 
vlv_rps_min_freq(struct intel_rps * rps)1416c349dbc7Sjsg static int vlv_rps_min_freq(struct intel_rps *rps)
1417c349dbc7Sjsg {
1418c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1419c349dbc7Sjsg 	u32 val;
1420c349dbc7Sjsg 
1421c349dbc7Sjsg 	val = vlv_punit_read(i915, PUNIT_REG_GPU_LFM) & 0xff;
1422c349dbc7Sjsg 	/*
1423c349dbc7Sjsg 	 * According to the BYT Punit GPU turbo HAS 1.1.6.3 the minimum value
1424c349dbc7Sjsg 	 * for the minimum frequency in GPLL mode is 0xc1. Contrary to this on
1425c349dbc7Sjsg 	 * a BYT-M B0 the above register contains 0xbf. Moreover when setting
1426c349dbc7Sjsg 	 * a frequency Punit will not allow values below 0xc0. Clamp it 0xc0
1427c349dbc7Sjsg 	 * to make sure it matches what Punit accepts.
1428c349dbc7Sjsg 	 */
1429c349dbc7Sjsg 	return max_t(u32, val, 0xc0);
1430c349dbc7Sjsg }
1431c349dbc7Sjsg 
vlv_rps_enable(struct intel_rps * rps)1432c349dbc7Sjsg static bool vlv_rps_enable(struct intel_rps *rps)
1433c349dbc7Sjsg {
1434c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
1435c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1436c349dbc7Sjsg 	u32 val;
1437c349dbc7Sjsg 
1438c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_DOWN_TIMEOUT, 1000000);
1439c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_UP_THRESHOLD, 59400);
1440c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_DOWN_THRESHOLD, 245000);
1441c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_UP_EI, 66000);
1442c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_DOWN_EI, 350000);
1443c349dbc7Sjsg 
1444c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_IDLE_HYSTERSIS, 10);
1445c349dbc7Sjsg 
1446c349dbc7Sjsg 	intel_uncore_write_fw(uncore, GEN6_RP_CONTROL,
1447c349dbc7Sjsg 			      GEN6_RP_MEDIA_TURBO |
1448c349dbc7Sjsg 			      GEN6_RP_MEDIA_HW_NORMAL_MODE |
1449c349dbc7Sjsg 			      GEN6_RP_MEDIA_IS_GFX |
1450c349dbc7Sjsg 			      GEN6_RP_ENABLE |
1451c349dbc7Sjsg 			      GEN6_RP_UP_BUSY_AVG |
1452c349dbc7Sjsg 			      GEN6_RP_DOWN_IDLE_CONT);
1453c349dbc7Sjsg 
1454ad8b1aafSjsg 	/* WaGsvRC0ResidencyMethod:vlv */
1455ad8b1aafSjsg 	rps->pm_events = GEN6_PM_RP_UP_EI_EXPIRED;
1456ad8b1aafSjsg 
1457c349dbc7Sjsg 	vlv_punit_get(i915);
1458c349dbc7Sjsg 
1459c349dbc7Sjsg 	/* Setting Fixed Bias */
1460c349dbc7Sjsg 	val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | VLV_BIAS_CPU_125_SOC_875;
1461c349dbc7Sjsg 	vlv_punit_write(i915, VLV_TURBO_SOC_OVERRIDE, val);
1462c349dbc7Sjsg 
1463c349dbc7Sjsg 	val = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);
1464c349dbc7Sjsg 
1465c349dbc7Sjsg 	vlv_punit_put(i915);
1466c349dbc7Sjsg 
1467c349dbc7Sjsg 	/* RPS code assumes GPLL is used */
1468c349dbc7Sjsg 	drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0,
1469c349dbc7Sjsg 		      "GPLL not enabled\n");
1470c349dbc7Sjsg 
14711bb76ff1Sjsg 	drm_dbg(&i915->drm, "GPLL enabled? %s\n",
14721bb76ff1Sjsg 		str_yes_no(val & GPLLENABLE));
1473ad8b1aafSjsg 	drm_dbg(&i915->drm, "GPU status: 0x%08x\n", val);
1474c349dbc7Sjsg 
1475c349dbc7Sjsg 	return rps_reset(rps);
1476c349dbc7Sjsg }
1477c349dbc7Sjsg 
__ips_gfx_val(struct intel_ips * ips)1478c349dbc7Sjsg static unsigned long __ips_gfx_val(struct intel_ips *ips)
1479c349dbc7Sjsg {
1480c349dbc7Sjsg 	struct intel_rps *rps = container_of(ips, typeof(*rps), ips);
1481c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
14825ca02815Sjsg 	unsigned int t, state1, state2;
1483c349dbc7Sjsg 	u32 pxvid, ext_v;
14845ca02815Sjsg 	u64 corr, corr2;
1485c349dbc7Sjsg 
1486c349dbc7Sjsg 	lockdep_assert_held(&mchdev_lock);
1487c349dbc7Sjsg 
1488c349dbc7Sjsg 	pxvid = intel_uncore_read(uncore, PXVFREQ(rps->cur_freq));
1489c349dbc7Sjsg 	pxvid = (pxvid >> 24) & 0x7f;
1490c349dbc7Sjsg 	ext_v = pvid_to_extvid(rps_to_i915(rps), pxvid);
1491c349dbc7Sjsg 
1492c349dbc7Sjsg 	state1 = ext_v;
1493c349dbc7Sjsg 
1494c349dbc7Sjsg 	/* Revel in the empirically derived constants */
1495c349dbc7Sjsg 
1496c349dbc7Sjsg 	/* Correction factor in 1/100000 units */
1497c349dbc7Sjsg 	t = ips_mch_val(uncore);
1498c349dbc7Sjsg 	if (t > 80)
1499c349dbc7Sjsg 		corr = t * 2349 + 135940;
1500c349dbc7Sjsg 	else if (t >= 50)
1501c349dbc7Sjsg 		corr = t * 964 + 29317;
1502c349dbc7Sjsg 	else /* < 50 */
1503c349dbc7Sjsg 		corr = t * 301 + 1004;
1504c349dbc7Sjsg 
15055ca02815Sjsg 	corr = div_u64(corr * 150142 * state1, 10000) - 78642;
15065ca02815Sjsg 	corr2 = div_u64(corr, 100000) * ips->corr;
1507c349dbc7Sjsg 
15085ca02815Sjsg 	state2 = div_u64(corr2 * state1, 10000);
1509c349dbc7Sjsg 	state2 /= 100; /* convert to mW */
1510c349dbc7Sjsg 
1511c349dbc7Sjsg 	__gen5_ips_update(ips);
1512c349dbc7Sjsg 
1513c349dbc7Sjsg 	return ips->gfx_power + state2;
1514c349dbc7Sjsg }
1515c349dbc7Sjsg 
has_busy_stats(struct intel_rps * rps)1516ad8b1aafSjsg static bool has_busy_stats(struct intel_rps *rps)
1517ad8b1aafSjsg {
1518ad8b1aafSjsg 	struct intel_engine_cs *engine;
1519ad8b1aafSjsg 	enum intel_engine_id id;
1520ad8b1aafSjsg 
1521ad8b1aafSjsg 	for_each_engine(engine, rps_to_gt(rps), id) {
1522ad8b1aafSjsg 		if (!intel_engine_supports_stats(engine))
1523ad8b1aafSjsg 			return false;
1524ad8b1aafSjsg 	}
1525ad8b1aafSjsg 
1526ad8b1aafSjsg 	return true;
1527ad8b1aafSjsg }
1528ad8b1aafSjsg 
intel_rps_enable(struct intel_rps * rps)1529c349dbc7Sjsg void intel_rps_enable(struct intel_rps *rps)
1530c349dbc7Sjsg {
1531c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1532c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
1533ad8b1aafSjsg 	bool enabled = false;
1534c349dbc7Sjsg 
1535ad8b1aafSjsg 	if (!HAS_RPS(i915))
1536c349dbc7Sjsg 		return;
1537c349dbc7Sjsg 
15385ca02815Sjsg 	if (rps_uses_slpc(rps))
15395ca02815Sjsg 		return;
15405ca02815Sjsg 
1541ad8b1aafSjsg 	intel_gt_check_clock_frequency(rps_to_gt(rps));
1542c349dbc7Sjsg 
1543ad8b1aafSjsg 	intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
1544ad8b1aafSjsg 	if (rps->max_freq <= rps->min_freq)
1545ad8b1aafSjsg 		/* leave disabled, no room for dynamic reclocking */;
1546ad8b1aafSjsg 	else if (IS_CHERRYVIEW(i915))
1547ad8b1aafSjsg 		enabled = chv_rps_enable(rps);
1548ad8b1aafSjsg 	else if (IS_VALLEYVIEW(i915))
1549ad8b1aafSjsg 		enabled = vlv_rps_enable(rps);
15505ca02815Sjsg 	else if (GRAPHICS_VER(i915) >= 9)
1551ad8b1aafSjsg 		enabled = gen9_rps_enable(rps);
15525ca02815Sjsg 	else if (GRAPHICS_VER(i915) >= 8)
1553ad8b1aafSjsg 		enabled = gen8_rps_enable(rps);
15545ca02815Sjsg 	else if (GRAPHICS_VER(i915) >= 6)
1555ad8b1aafSjsg 		enabled = gen6_rps_enable(rps);
1556ad8b1aafSjsg 	else if (IS_IRONLAKE_M(i915))
1557ad8b1aafSjsg 		enabled = gen5_rps_enable(rps);
1558ad8b1aafSjsg 	else
15595ca02815Sjsg 		MISSING_CASE(GRAPHICS_VER(i915));
1560ad8b1aafSjsg 	intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
1561ad8b1aafSjsg 	if (!enabled)
1562ad8b1aafSjsg 		return;
1563ad8b1aafSjsg 
1564ad8b1aafSjsg 	GT_TRACE(rps_to_gt(rps),
1565f005ef32Sjsg 		 "min:%x, max:%x, freq:[%d, %d], thresholds:[%u, %u]\n",
1566ad8b1aafSjsg 		 rps->min_freq, rps->max_freq,
1567ad8b1aafSjsg 		 intel_gpu_freq(rps, rps->min_freq),
1568f005ef32Sjsg 		 intel_gpu_freq(rps, rps->max_freq),
1569f005ef32Sjsg 		 rps->power.up_threshold,
1570f005ef32Sjsg 		 rps->power.down_threshold);
1571ad8b1aafSjsg 
1572ad8b1aafSjsg 	GEM_BUG_ON(rps->max_freq < rps->min_freq);
1573ad8b1aafSjsg 	GEM_BUG_ON(rps->idle_freq > rps->max_freq);
1574ad8b1aafSjsg 
1575ad8b1aafSjsg 	GEM_BUG_ON(rps->efficient_freq < rps->min_freq);
1576ad8b1aafSjsg 	GEM_BUG_ON(rps->efficient_freq > rps->max_freq);
1577ad8b1aafSjsg 
1578ad8b1aafSjsg 	if (has_busy_stats(rps))
1579ad8b1aafSjsg 		intel_rps_set_timer(rps);
15801bb76ff1Sjsg 	else if (GRAPHICS_VER(i915) >= 6 && GRAPHICS_VER(i915) <= 11)
1581ad8b1aafSjsg 		intel_rps_set_interrupts(rps);
1582ad8b1aafSjsg 	else
1583ad8b1aafSjsg 		/* Ironlake currently uses intel_ips.ko */ {}
1584ad8b1aafSjsg 
1585ad8b1aafSjsg 	intel_rps_set_enabled(rps);
1586c349dbc7Sjsg }
1587c349dbc7Sjsg 
gen6_rps_disable(struct intel_rps * rps)1588c349dbc7Sjsg static void gen6_rps_disable(struct intel_rps *rps)
1589c349dbc7Sjsg {
1590c349dbc7Sjsg 	set(rps_to_uncore(rps), GEN6_RP_CONTROL, 0);
1591c349dbc7Sjsg }
1592c349dbc7Sjsg 
intel_rps_disable(struct intel_rps * rps)1593c349dbc7Sjsg void intel_rps_disable(struct intel_rps *rps)
1594c349dbc7Sjsg {
1595c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1596c349dbc7Sjsg 
15971bb76ff1Sjsg 	if (!intel_rps_is_enabled(rps))
15981bb76ff1Sjsg 		return;
15991bb76ff1Sjsg 
1600ad8b1aafSjsg 	intel_rps_clear_enabled(rps);
1601ad8b1aafSjsg 	intel_rps_clear_interrupts(rps);
1602ad8b1aafSjsg 	intel_rps_clear_timer(rps);
1603c349dbc7Sjsg 
16045ca02815Sjsg 	if (GRAPHICS_VER(i915) >= 6)
1605c349dbc7Sjsg 		gen6_rps_disable(rps);
1606c349dbc7Sjsg 	else if (IS_IRONLAKE_M(i915))
1607c349dbc7Sjsg 		gen5_rps_disable(rps);
1608c349dbc7Sjsg }
1609c349dbc7Sjsg 
byt_gpu_freq(struct intel_rps * rps,int val)1610c349dbc7Sjsg static int byt_gpu_freq(struct intel_rps *rps, int val)
1611c349dbc7Sjsg {
1612c349dbc7Sjsg 	/*
1613c349dbc7Sjsg 	 * N = val - 0xb7
1614c349dbc7Sjsg 	 * Slow = Fast = GPLL ref * N
1615c349dbc7Sjsg 	 */
1616c349dbc7Sjsg 	return DIV_ROUND_CLOSEST(rps->gpll_ref_freq * (val - 0xb7), 1000);
1617c349dbc7Sjsg }
1618c349dbc7Sjsg 
byt_freq_opcode(struct intel_rps * rps,int val)1619c349dbc7Sjsg static int byt_freq_opcode(struct intel_rps *rps, int val)
1620c349dbc7Sjsg {
1621c349dbc7Sjsg 	return DIV_ROUND_CLOSEST(1000 * val, rps->gpll_ref_freq) + 0xb7;
1622c349dbc7Sjsg }
1623c349dbc7Sjsg 
chv_gpu_freq(struct intel_rps * rps,int val)1624c349dbc7Sjsg static int chv_gpu_freq(struct intel_rps *rps, int val)
1625c349dbc7Sjsg {
1626c349dbc7Sjsg 	/*
1627c349dbc7Sjsg 	 * N = val / 2
1628c349dbc7Sjsg 	 * CU (slow) = CU2x (fast) / 2 = GPLL ref * N / 2
1629c349dbc7Sjsg 	 */
1630c349dbc7Sjsg 	return DIV_ROUND_CLOSEST(rps->gpll_ref_freq * val, 2 * 2 * 1000);
1631c349dbc7Sjsg }
1632c349dbc7Sjsg 
chv_freq_opcode(struct intel_rps * rps,int val)1633c349dbc7Sjsg static int chv_freq_opcode(struct intel_rps *rps, int val)
1634c349dbc7Sjsg {
1635c349dbc7Sjsg 	/* CHV needs even values */
1636c349dbc7Sjsg 	return DIV_ROUND_CLOSEST(2 * 1000 * val, rps->gpll_ref_freq) * 2;
1637c349dbc7Sjsg }
1638c349dbc7Sjsg 
intel_gpu_freq(struct intel_rps * rps,int val)1639c349dbc7Sjsg int intel_gpu_freq(struct intel_rps *rps, int val)
1640c349dbc7Sjsg {
1641c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1642c349dbc7Sjsg 
16435ca02815Sjsg 	if (GRAPHICS_VER(i915) >= 9)
1644c349dbc7Sjsg 		return DIV_ROUND_CLOSEST(val * GT_FREQUENCY_MULTIPLIER,
1645c349dbc7Sjsg 					 GEN9_FREQ_SCALER);
1646c349dbc7Sjsg 	else if (IS_CHERRYVIEW(i915))
1647c349dbc7Sjsg 		return chv_gpu_freq(rps, val);
1648c349dbc7Sjsg 	else if (IS_VALLEYVIEW(i915))
1649c349dbc7Sjsg 		return byt_gpu_freq(rps, val);
16505ca02815Sjsg 	else if (GRAPHICS_VER(i915) >= 6)
1651c349dbc7Sjsg 		return val * GT_FREQUENCY_MULTIPLIER;
16525ca02815Sjsg 	else
16535ca02815Sjsg 		return val;
1654c349dbc7Sjsg }
1655c349dbc7Sjsg 
intel_freq_opcode(struct intel_rps * rps,int val)1656c349dbc7Sjsg int intel_freq_opcode(struct intel_rps *rps, int val)
1657c349dbc7Sjsg {
1658c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1659c349dbc7Sjsg 
16605ca02815Sjsg 	if (GRAPHICS_VER(i915) >= 9)
1661c349dbc7Sjsg 		return DIV_ROUND_CLOSEST(val * GEN9_FREQ_SCALER,
1662c349dbc7Sjsg 					 GT_FREQUENCY_MULTIPLIER);
1663c349dbc7Sjsg 	else if (IS_CHERRYVIEW(i915))
1664c349dbc7Sjsg 		return chv_freq_opcode(rps, val);
1665c349dbc7Sjsg 	else if (IS_VALLEYVIEW(i915))
1666c349dbc7Sjsg 		return byt_freq_opcode(rps, val);
16675ca02815Sjsg 	else if (GRAPHICS_VER(i915) >= 6)
1668c349dbc7Sjsg 		return DIV_ROUND_CLOSEST(val, GT_FREQUENCY_MULTIPLIER);
16695ca02815Sjsg 	else
16705ca02815Sjsg 		return val;
1671c349dbc7Sjsg }
1672c349dbc7Sjsg 
vlv_init_gpll_ref_freq(struct intel_rps * rps)1673c349dbc7Sjsg static void vlv_init_gpll_ref_freq(struct intel_rps *rps)
1674c349dbc7Sjsg {
1675c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1676c349dbc7Sjsg 
1677c349dbc7Sjsg 	rps->gpll_ref_freq =
1678c349dbc7Sjsg 		vlv_get_cck_clock(i915, "GPLL ref",
1679c349dbc7Sjsg 				  CCK_GPLL_CLOCK_CONTROL,
1680c349dbc7Sjsg 				  i915->czclk_freq);
1681c349dbc7Sjsg 
1682ad8b1aafSjsg 	drm_dbg(&i915->drm, "GPLL reference freq: %d kHz\n",
1683ad8b1aafSjsg 		rps->gpll_ref_freq);
1684c349dbc7Sjsg }
1685c349dbc7Sjsg 
vlv_rps_init(struct intel_rps * rps)1686c349dbc7Sjsg static void vlv_rps_init(struct intel_rps *rps)
1687c349dbc7Sjsg {
1688c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1689c349dbc7Sjsg 
1690c349dbc7Sjsg 	vlv_iosf_sb_get(i915,
1691c349dbc7Sjsg 			BIT(VLV_IOSF_SB_PUNIT) |
1692c349dbc7Sjsg 			BIT(VLV_IOSF_SB_NC) |
1693c349dbc7Sjsg 			BIT(VLV_IOSF_SB_CCK));
1694c349dbc7Sjsg 
1695c349dbc7Sjsg 	vlv_init_gpll_ref_freq(rps);
1696c349dbc7Sjsg 
1697c349dbc7Sjsg 	rps->max_freq = vlv_rps_max_freq(rps);
1698c349dbc7Sjsg 	rps->rp0_freq = rps->max_freq;
1699ad8b1aafSjsg 	drm_dbg(&i915->drm, "max GPU freq: %d MHz (%u)\n",
1700ad8b1aafSjsg 		intel_gpu_freq(rps, rps->max_freq), rps->max_freq);
1701c349dbc7Sjsg 
1702c349dbc7Sjsg 	rps->efficient_freq = vlv_rps_rpe_freq(rps);
1703ad8b1aafSjsg 	drm_dbg(&i915->drm, "RPe GPU freq: %d MHz (%u)\n",
1704ad8b1aafSjsg 		intel_gpu_freq(rps, rps->efficient_freq), rps->efficient_freq);
1705c349dbc7Sjsg 
1706c349dbc7Sjsg 	rps->rp1_freq = vlv_rps_guar_freq(rps);
1707ad8b1aafSjsg 	drm_dbg(&i915->drm, "RP1(Guar Freq) GPU freq: %d MHz (%u)\n",
1708ad8b1aafSjsg 		intel_gpu_freq(rps, rps->rp1_freq), rps->rp1_freq);
1709c349dbc7Sjsg 
1710c349dbc7Sjsg 	rps->min_freq = vlv_rps_min_freq(rps);
1711ad8b1aafSjsg 	drm_dbg(&i915->drm, "min GPU freq: %d MHz (%u)\n",
1712ad8b1aafSjsg 		intel_gpu_freq(rps, rps->min_freq), rps->min_freq);
1713c349dbc7Sjsg 
1714c349dbc7Sjsg 	vlv_iosf_sb_put(i915,
1715c349dbc7Sjsg 			BIT(VLV_IOSF_SB_PUNIT) |
1716c349dbc7Sjsg 			BIT(VLV_IOSF_SB_NC) |
1717c349dbc7Sjsg 			BIT(VLV_IOSF_SB_CCK));
1718c349dbc7Sjsg }
1719c349dbc7Sjsg 
chv_rps_init(struct intel_rps * rps)1720c349dbc7Sjsg static void chv_rps_init(struct intel_rps *rps)
1721c349dbc7Sjsg {
1722c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1723c349dbc7Sjsg 
1724c349dbc7Sjsg 	vlv_iosf_sb_get(i915,
1725c349dbc7Sjsg 			BIT(VLV_IOSF_SB_PUNIT) |
1726c349dbc7Sjsg 			BIT(VLV_IOSF_SB_NC) |
1727c349dbc7Sjsg 			BIT(VLV_IOSF_SB_CCK));
1728c349dbc7Sjsg 
1729c349dbc7Sjsg 	vlv_init_gpll_ref_freq(rps);
1730c349dbc7Sjsg 
1731c349dbc7Sjsg 	rps->max_freq = chv_rps_max_freq(rps);
1732c349dbc7Sjsg 	rps->rp0_freq = rps->max_freq;
1733ad8b1aafSjsg 	drm_dbg(&i915->drm, "max GPU freq: %d MHz (%u)\n",
1734ad8b1aafSjsg 		intel_gpu_freq(rps, rps->max_freq), rps->max_freq);
1735c349dbc7Sjsg 
1736c349dbc7Sjsg 	rps->efficient_freq = chv_rps_rpe_freq(rps);
1737ad8b1aafSjsg 	drm_dbg(&i915->drm, "RPe GPU freq: %d MHz (%u)\n",
1738ad8b1aafSjsg 		intel_gpu_freq(rps, rps->efficient_freq), rps->efficient_freq);
1739c349dbc7Sjsg 
1740c349dbc7Sjsg 	rps->rp1_freq = chv_rps_guar_freq(rps);
1741ad8b1aafSjsg 	drm_dbg(&i915->drm, "RP1(Guar) GPU freq: %d MHz (%u)\n",
1742ad8b1aafSjsg 		intel_gpu_freq(rps, rps->rp1_freq), rps->rp1_freq);
1743c349dbc7Sjsg 
1744c349dbc7Sjsg 	rps->min_freq = chv_rps_min_freq(rps);
1745ad8b1aafSjsg 	drm_dbg(&i915->drm, "min GPU freq: %d MHz (%u)\n",
1746ad8b1aafSjsg 		intel_gpu_freq(rps, rps->min_freq), rps->min_freq);
1747c349dbc7Sjsg 
1748c349dbc7Sjsg 	vlv_iosf_sb_put(i915,
1749c349dbc7Sjsg 			BIT(VLV_IOSF_SB_PUNIT) |
1750c349dbc7Sjsg 			BIT(VLV_IOSF_SB_NC) |
1751c349dbc7Sjsg 			BIT(VLV_IOSF_SB_CCK));
1752c349dbc7Sjsg 
1753c349dbc7Sjsg 	drm_WARN_ONCE(&i915->drm, (rps->max_freq | rps->efficient_freq |
1754c349dbc7Sjsg 				   rps->rp1_freq | rps->min_freq) & 1,
1755c349dbc7Sjsg 		      "Odd GPU freq values\n");
1756c349dbc7Sjsg }
1757c349dbc7Sjsg 
vlv_c0_read(struct intel_uncore * uncore,struct intel_rps_ei * ei)1758c349dbc7Sjsg static void vlv_c0_read(struct intel_uncore *uncore, struct intel_rps_ei *ei)
1759c349dbc7Sjsg {
1760c349dbc7Sjsg 	ei->ktime = ktime_get_raw();
1761c349dbc7Sjsg 	ei->render_c0 = intel_uncore_read(uncore, VLV_RENDER_C0_COUNT);
1762c349dbc7Sjsg 	ei->media_c0 = intel_uncore_read(uncore, VLV_MEDIA_C0_COUNT);
1763c349dbc7Sjsg }
1764c349dbc7Sjsg 
vlv_wa_c0_ei(struct intel_rps * rps,u32 pm_iir)1765c349dbc7Sjsg static u32 vlv_wa_c0_ei(struct intel_rps *rps, u32 pm_iir)
1766c349dbc7Sjsg {
1767c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
1768c349dbc7Sjsg 	const struct intel_rps_ei *prev = &rps->ei;
1769c349dbc7Sjsg 	struct intel_rps_ei now;
1770c349dbc7Sjsg 	u32 events = 0;
1771c349dbc7Sjsg 
1772c349dbc7Sjsg 	if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0)
1773c349dbc7Sjsg 		return 0;
1774c349dbc7Sjsg 
1775c349dbc7Sjsg 	vlv_c0_read(uncore, &now);
1776c349dbc7Sjsg 
1777c349dbc7Sjsg #ifdef __linux__
1778c349dbc7Sjsg 	if (prev->ktime) {
1779c349dbc7Sjsg #else
1780c349dbc7Sjsg 	if (ktime_to_ns(prev->ktime)) {
1781c349dbc7Sjsg #endif
1782c349dbc7Sjsg 		u64 time, c0;
1783c349dbc7Sjsg 		u32 render, media;
1784c349dbc7Sjsg 
1785c349dbc7Sjsg 		time = ktime_us_delta(now.ktime, prev->ktime);
1786c349dbc7Sjsg 
1787c349dbc7Sjsg 		time *= rps_to_i915(rps)->czclk_freq;
1788c349dbc7Sjsg 
1789c349dbc7Sjsg 		/* Workload can be split between render + media,
1790c349dbc7Sjsg 		 * e.g. SwapBuffers being blitted in X after being rendered in
1791c349dbc7Sjsg 		 * mesa. To account for this we need to combine both engines
1792c349dbc7Sjsg 		 * into our activity counter.
1793c349dbc7Sjsg 		 */
1794c349dbc7Sjsg 		render = now.render_c0 - prev->render_c0;
1795c349dbc7Sjsg 		media = now.media_c0 - prev->media_c0;
1796c349dbc7Sjsg 		c0 = max(render, media);
1797c349dbc7Sjsg 		c0 *= 1000 * 100 << 8; /* to usecs and scale to threshold% */
1798c349dbc7Sjsg 
1799c349dbc7Sjsg 		if (c0 > time * rps->power.up_threshold)
1800c349dbc7Sjsg 			events = GEN6_PM_RP_UP_THRESHOLD;
1801c349dbc7Sjsg 		else if (c0 < time * rps->power.down_threshold)
1802c349dbc7Sjsg 			events = GEN6_PM_RP_DOWN_THRESHOLD;
1803c349dbc7Sjsg 	}
1804c349dbc7Sjsg 
1805c349dbc7Sjsg 	rps->ei = now;
1806c349dbc7Sjsg 	return events;
1807c349dbc7Sjsg }
1808c349dbc7Sjsg 
1809c349dbc7Sjsg static void rps_work(struct work_struct *work)
1810c349dbc7Sjsg {
1811c349dbc7Sjsg 	struct intel_rps *rps = container_of(work, typeof(*rps), work);
1812c349dbc7Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
1813ad8b1aafSjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1814c349dbc7Sjsg 	bool client_boost = false;
1815c349dbc7Sjsg 	int new_freq, adj, min, max;
1816c349dbc7Sjsg 	u32 pm_iir = 0;
1817c349dbc7Sjsg 
18181bb76ff1Sjsg 	spin_lock_irq(gt->irq_lock);
1819ad8b1aafSjsg 	pm_iir = fetch_and_zero(&rps->pm_iir) & rps->pm_events;
1820c349dbc7Sjsg 	client_boost = atomic_read(&rps->num_waiters);
18211bb76ff1Sjsg 	spin_unlock_irq(gt->irq_lock);
1822c349dbc7Sjsg 
1823c349dbc7Sjsg 	/* Make sure we didn't queue anything we're not going to process. */
1824c349dbc7Sjsg 	if (!pm_iir && !client_boost)
1825c349dbc7Sjsg 		goto out;
1826c349dbc7Sjsg 
1827c349dbc7Sjsg 	mutex_lock(&rps->lock);
1828ad8b1aafSjsg 	if (!intel_rps_is_active(rps)) {
1829ad8b1aafSjsg 		mutex_unlock(&rps->lock);
1830ad8b1aafSjsg 		return;
1831ad8b1aafSjsg 	}
1832c349dbc7Sjsg 
1833c349dbc7Sjsg 	pm_iir |= vlv_wa_c0_ei(rps, pm_iir);
1834c349dbc7Sjsg 
1835c349dbc7Sjsg 	adj = rps->last_adj;
1836c349dbc7Sjsg 	new_freq = rps->cur_freq;
1837c349dbc7Sjsg 	min = rps->min_freq_softlimit;
1838c349dbc7Sjsg 	max = rps->max_freq_softlimit;
1839c349dbc7Sjsg 	if (client_boost)
1840c349dbc7Sjsg 		max = rps->max_freq;
1841ad8b1aafSjsg 
1842ad8b1aafSjsg 	GT_TRACE(gt,
1843ad8b1aafSjsg 		 "pm_iir:%x, client_boost:%s, last:%d, cur:%x, min:%x, max:%x\n",
18441bb76ff1Sjsg 		 pm_iir, str_yes_no(client_boost),
1845ad8b1aafSjsg 		 adj, new_freq, min, max);
1846ad8b1aafSjsg 
1847c349dbc7Sjsg 	if (client_boost && new_freq < rps->boost_freq) {
1848c349dbc7Sjsg 		new_freq = rps->boost_freq;
1849c349dbc7Sjsg 		adj = 0;
1850c349dbc7Sjsg 	} else if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
1851c349dbc7Sjsg 		if (adj > 0)
1852c349dbc7Sjsg 			adj *= 2;
1853c349dbc7Sjsg 		else /* CHV needs even encode values */
1854c349dbc7Sjsg 			adj = IS_CHERRYVIEW(gt->i915) ? 2 : 1;
1855c349dbc7Sjsg 
1856c349dbc7Sjsg 		if (new_freq >= rps->max_freq_softlimit)
1857c349dbc7Sjsg 			adj = 0;
1858c349dbc7Sjsg 	} else if (client_boost) {
1859c349dbc7Sjsg 		adj = 0;
1860c349dbc7Sjsg 	} else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) {
1861c349dbc7Sjsg 		if (rps->cur_freq > rps->efficient_freq)
1862c349dbc7Sjsg 			new_freq = rps->efficient_freq;
1863c349dbc7Sjsg 		else if (rps->cur_freq > rps->min_freq_softlimit)
1864c349dbc7Sjsg 			new_freq = rps->min_freq_softlimit;
1865c349dbc7Sjsg 		adj = 0;
1866c349dbc7Sjsg 	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
1867c349dbc7Sjsg 		if (adj < 0)
1868c349dbc7Sjsg 			adj *= 2;
1869c349dbc7Sjsg 		else /* CHV needs even encode values */
1870c349dbc7Sjsg 			adj = IS_CHERRYVIEW(gt->i915) ? -2 : -1;
1871c349dbc7Sjsg 
1872c349dbc7Sjsg 		if (new_freq <= rps->min_freq_softlimit)
1873c349dbc7Sjsg 			adj = 0;
1874c349dbc7Sjsg 	} else { /* unknown event */
1875c349dbc7Sjsg 		adj = 0;
1876c349dbc7Sjsg 	}
1877c349dbc7Sjsg 
1878c349dbc7Sjsg 	/*
1879ad8b1aafSjsg 	 * sysfs frequency limits may have snuck in while
1880ad8b1aafSjsg 	 * servicing the interrupt
1881c349dbc7Sjsg 	 */
1882c349dbc7Sjsg 	new_freq += adj;
1883c349dbc7Sjsg 	new_freq = clamp_t(int, new_freq, min, max);
1884c349dbc7Sjsg 
1885c349dbc7Sjsg 	if (intel_rps_set(rps, new_freq)) {
1886ad8b1aafSjsg 		drm_dbg(&i915->drm, "Failed to set new GPU frequency\n");
1887ad8b1aafSjsg 		adj = 0;
1888c349dbc7Sjsg 	}
1889ad8b1aafSjsg 	rps->last_adj = adj;
1890c349dbc7Sjsg 
1891c349dbc7Sjsg 	mutex_unlock(&rps->lock);
1892c349dbc7Sjsg 
1893c349dbc7Sjsg out:
18941bb76ff1Sjsg 	spin_lock_irq(gt->irq_lock);
1895c349dbc7Sjsg 	gen6_gt_pm_unmask_irq(gt, rps->pm_events);
18961bb76ff1Sjsg 	spin_unlock_irq(gt->irq_lock);
1897c349dbc7Sjsg }
1898c349dbc7Sjsg 
1899c349dbc7Sjsg void gen11_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
1900c349dbc7Sjsg {
1901c349dbc7Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
1902c349dbc7Sjsg 	const u32 events = rps->pm_events & pm_iir;
1903c349dbc7Sjsg 
19041bb76ff1Sjsg 	lockdep_assert_held(gt->irq_lock);
1905c349dbc7Sjsg 
1906c349dbc7Sjsg 	if (unlikely(!events))
1907c349dbc7Sjsg 		return;
1908c349dbc7Sjsg 
1909ad8b1aafSjsg 	GT_TRACE(gt, "irq events:%x\n", events);
1910ad8b1aafSjsg 
1911c349dbc7Sjsg 	gen6_gt_pm_mask_irq(gt, events);
1912c349dbc7Sjsg 
1913c349dbc7Sjsg 	rps->pm_iir |= events;
1914f005ef32Sjsg 	queue_work(gt->i915->unordered_wq, &rps->work);
1915c349dbc7Sjsg }
1916c349dbc7Sjsg 
1917c349dbc7Sjsg void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
1918c349dbc7Sjsg {
1919c349dbc7Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
1920c349dbc7Sjsg 	u32 events;
1921c349dbc7Sjsg 
1922ad8b1aafSjsg 	events = pm_iir & rps->pm_events;
1923c349dbc7Sjsg 	if (events) {
19241bb76ff1Sjsg 		spin_lock(gt->irq_lock);
1925c349dbc7Sjsg 
1926ad8b1aafSjsg 		GT_TRACE(gt, "irq events:%x\n", events);
1927ad8b1aafSjsg 
1928c349dbc7Sjsg 		gen6_gt_pm_mask_irq(gt, events);
1929c349dbc7Sjsg 		rps->pm_iir |= events;
1930c349dbc7Sjsg 
1931f005ef32Sjsg 		queue_work(gt->i915->unordered_wq, &rps->work);
19321bb76ff1Sjsg 		spin_unlock(gt->irq_lock);
1933c349dbc7Sjsg 	}
1934c349dbc7Sjsg 
19355ca02815Sjsg 	if (GRAPHICS_VER(gt->i915) >= 8)
1936c349dbc7Sjsg 		return;
1937c349dbc7Sjsg 
1938c349dbc7Sjsg 	if (pm_iir & PM_VEBOX_USER_INTERRUPT)
19395ca02815Sjsg 		intel_engine_cs_irq(gt->engine[VECS0], pm_iir >> 10);
1940c349dbc7Sjsg 
1941c349dbc7Sjsg 	if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT)
1942f005ef32Sjsg 		drm_dbg(&rps_to_i915(rps)->drm,
1943f005ef32Sjsg 			"Command parser error, pm_iir 0x%08x\n", pm_iir);
1944c349dbc7Sjsg }
1945c349dbc7Sjsg 
1946c349dbc7Sjsg void gen5_rps_irq_handler(struct intel_rps *rps)
1947c349dbc7Sjsg {
1948c349dbc7Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
1949c349dbc7Sjsg 	u32 busy_up, busy_down, max_avg, min_avg;
1950c349dbc7Sjsg 	u8 new_freq;
1951c349dbc7Sjsg 
1952c349dbc7Sjsg 	spin_lock(&mchdev_lock);
1953c349dbc7Sjsg 
1954c349dbc7Sjsg 	intel_uncore_write16(uncore,
1955c349dbc7Sjsg 			     MEMINTRSTS,
1956c349dbc7Sjsg 			     intel_uncore_read(uncore, MEMINTRSTS));
1957c349dbc7Sjsg 
1958c349dbc7Sjsg 	intel_uncore_write16(uncore, MEMINTRSTS, MEMINT_EVAL_CHG);
1959c349dbc7Sjsg 	busy_up = intel_uncore_read(uncore, RCPREVBSYTUPAVG);
1960c349dbc7Sjsg 	busy_down = intel_uncore_read(uncore, RCPREVBSYTDNAVG);
1961c349dbc7Sjsg 	max_avg = intel_uncore_read(uncore, RCBMAXAVG);
1962c349dbc7Sjsg 	min_avg = intel_uncore_read(uncore, RCBMINAVG);
1963c349dbc7Sjsg 
1964c349dbc7Sjsg 	/* Handle RCS change request from hw */
1965c349dbc7Sjsg 	new_freq = rps->cur_freq;
1966c349dbc7Sjsg 	if (busy_up > max_avg)
1967c349dbc7Sjsg 		new_freq++;
1968c349dbc7Sjsg 	else if (busy_down < min_avg)
1969c349dbc7Sjsg 		new_freq--;
1970c349dbc7Sjsg 	new_freq = clamp(new_freq,
1971c349dbc7Sjsg 			 rps->min_freq_softlimit,
1972c349dbc7Sjsg 			 rps->max_freq_softlimit);
1973c349dbc7Sjsg 
19745ca02815Sjsg 	if (new_freq != rps->cur_freq && !__gen5_rps_set(rps, new_freq))
1975c349dbc7Sjsg 		rps->cur_freq = new_freq;
1976c349dbc7Sjsg 
1977c349dbc7Sjsg 	spin_unlock(&mchdev_lock);
1978c349dbc7Sjsg }
1979c349dbc7Sjsg 
1980c349dbc7Sjsg void intel_rps_init_early(struct intel_rps *rps)
1981c349dbc7Sjsg {
1982c349dbc7Sjsg 	rw_init(&rps->lock, "rpslk");
1983c349dbc7Sjsg 	rw_init(&rps->power.mutex, "rpspwr");
1984c349dbc7Sjsg 
1985c349dbc7Sjsg 	INIT_WORK(&rps->work, rps_work);
1986ad8b1aafSjsg #ifdef __linux__
1987ad8b1aafSjsg 	timer_setup(&rps->timer, rps_timer, 0);
1988ad8b1aafSjsg #else
1989ad8b1aafSjsg 	timeout_set(&rps->timer, rps_timer, rps);
1990ad8b1aafSjsg #endif
1991c349dbc7Sjsg 
1992c349dbc7Sjsg 	atomic_set(&rps->num_waiters, 0);
1993c349dbc7Sjsg }
1994c349dbc7Sjsg 
1995c349dbc7Sjsg void intel_rps_init(struct intel_rps *rps)
1996c349dbc7Sjsg {
1997c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
1998c349dbc7Sjsg 
19995ca02815Sjsg 	if (rps_uses_slpc(rps))
20005ca02815Sjsg 		return;
20015ca02815Sjsg 
2002c349dbc7Sjsg 	if (IS_CHERRYVIEW(i915))
2003c349dbc7Sjsg 		chv_rps_init(rps);
2004c349dbc7Sjsg 	else if (IS_VALLEYVIEW(i915))
2005c349dbc7Sjsg 		vlv_rps_init(rps);
20065ca02815Sjsg 	else if (GRAPHICS_VER(i915) >= 6)
2007c349dbc7Sjsg 		gen6_rps_init(rps);
2008c349dbc7Sjsg 	else if (IS_IRONLAKE_M(i915))
2009c349dbc7Sjsg 		gen5_rps_init(rps);
2010c349dbc7Sjsg 
2011c349dbc7Sjsg 	/* Derive initial user preferences/limits from the hardware limits */
2012c349dbc7Sjsg 	rps->max_freq_softlimit = rps->max_freq;
20131bb76ff1Sjsg 	rps_to_gt(rps)->defaults.max_freq = rps->max_freq_softlimit;
2014c349dbc7Sjsg 	rps->min_freq_softlimit = rps->min_freq;
20151bb76ff1Sjsg 	rps_to_gt(rps)->defaults.min_freq = rps->min_freq_softlimit;
2016c349dbc7Sjsg 
2017c349dbc7Sjsg 	/* After setting max-softlimit, find the overclock max freq */
20185ca02815Sjsg 	if (GRAPHICS_VER(i915) == 6 || IS_IVYBRIDGE(i915) || IS_HASWELL(i915)) {
2019c349dbc7Sjsg 		u32 params = 0;
2020c349dbc7Sjsg 
20211bb76ff1Sjsg 		snb_pcode_read(rps_to_gt(rps)->uncore, GEN6_READ_OC_PARAMS, &params, NULL);
2022c349dbc7Sjsg 		if (params & BIT(31)) { /* OC supported */
2023ad8b1aafSjsg 			drm_dbg(&i915->drm,
2024ad8b1aafSjsg 				"Overclocking supported, max: %dMHz, overclock: %dMHz\n",
2025c349dbc7Sjsg 				(rps->max_freq & 0xff) * 50,
2026c349dbc7Sjsg 				(params & 0xff) * 50);
2027c349dbc7Sjsg 			rps->max_freq = params & 0xff;
2028c349dbc7Sjsg 		}
2029c349dbc7Sjsg 	}
2030c349dbc7Sjsg 
2031f005ef32Sjsg 	/* Set default thresholds in % */
2032f005ef32Sjsg 	rps->power.up_threshold = 95;
2033f005ef32Sjsg 	rps_to_gt(rps)->defaults.rps_up_threshold = rps->power.up_threshold;
2034f005ef32Sjsg 	rps->power.down_threshold = 85;
2035f005ef32Sjsg 	rps_to_gt(rps)->defaults.rps_down_threshold = rps->power.down_threshold;
2036f005ef32Sjsg 
2037c349dbc7Sjsg 	/* Finally allow us to boost to max by default */
2038c349dbc7Sjsg 	rps->boost_freq = rps->max_freq;
2039c349dbc7Sjsg 	rps->idle_freq = rps->min_freq;
2040ad8b1aafSjsg 
2041ad8b1aafSjsg 	/* Start in the middle, from here we will autotune based on workload */
2042ad8b1aafSjsg 	rps->cur_freq = rps->efficient_freq;
2043c349dbc7Sjsg 
2044c349dbc7Sjsg 	rps->pm_intrmsk_mbz = 0;
2045c349dbc7Sjsg 
2046c349dbc7Sjsg 	/*
2047c349dbc7Sjsg 	 * SNB,IVB,HSW can while VLV,CHV may hard hang on looping batchbuffer
2048c349dbc7Sjsg 	 * if GEN6_PM_UP_EI_EXPIRED is masked.
2049c349dbc7Sjsg 	 *
2050c349dbc7Sjsg 	 * TODO: verify if this can be reproduced on VLV,CHV.
2051c349dbc7Sjsg 	 */
20525ca02815Sjsg 	if (GRAPHICS_VER(i915) <= 7)
2053c349dbc7Sjsg 		rps->pm_intrmsk_mbz |= GEN6_PM_RP_UP_EI_EXPIRED;
2054c349dbc7Sjsg 
20555ca02815Sjsg 	if (GRAPHICS_VER(i915) >= 8 && GRAPHICS_VER(i915) < 11)
2056c349dbc7Sjsg 		rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC;
20575ca02815Sjsg 
20585ca02815Sjsg 	/* GuC needs ARAT expired interrupt unmasked */
20595ca02815Sjsg 	if (intel_uc_uses_guc_submission(&rps_to_gt(rps)->uc))
20605ca02815Sjsg 		rps->pm_intrmsk_mbz |= ARAT_EXPIRED_INTRMSK;
2061c349dbc7Sjsg }
2062c349dbc7Sjsg 
2063ad8b1aafSjsg void intel_rps_sanitize(struct intel_rps *rps)
2064ad8b1aafSjsg {
20655ca02815Sjsg 	if (rps_uses_slpc(rps))
20665ca02815Sjsg 		return;
20675ca02815Sjsg 
20685ca02815Sjsg 	if (GRAPHICS_VER(rps_to_i915(rps)) >= 6)
2069ad8b1aafSjsg 		rps_disable_interrupts(rps);
2070ad8b1aafSjsg }
2071ad8b1aafSjsg 
2072f005ef32Sjsg u32 intel_rps_read_rpstat(struct intel_rps *rps)
2073f005ef32Sjsg {
2074f005ef32Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
2075f005ef32Sjsg 	i915_reg_t rpstat;
2076f005ef32Sjsg 
2077f005ef32Sjsg 	rpstat = (GRAPHICS_VER(i915) >= 12) ? GEN12_RPSTAT1 : GEN6_RPSTAT1;
2078f005ef32Sjsg 
2079f005ef32Sjsg 	return intel_uncore_read(rps_to_gt(rps)->uncore, rpstat);
2080f005ef32Sjsg }
2081f005ef32Sjsg 
2082f005ef32Sjsg static u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat)
2083c349dbc7Sjsg {
2084c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
2085c349dbc7Sjsg 	u32 cagf;
2086c349dbc7Sjsg 
2087f005ef32Sjsg 	if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
2088f005ef32Sjsg 		cagf = REG_FIELD_GET(MTL_CAGF_MASK, rpstat);
2089f005ef32Sjsg 	else if (GRAPHICS_VER(i915) >= 12)
2090f005ef32Sjsg 		cagf = REG_FIELD_GET(GEN12_CAGF_MASK, rpstat);
2091f005ef32Sjsg 	else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
2092f005ef32Sjsg 		cagf = REG_FIELD_GET(RPE_MASK, rpstat);
20935ca02815Sjsg 	else if (GRAPHICS_VER(i915) >= 9)
2094f005ef32Sjsg 		cagf = REG_FIELD_GET(GEN9_CAGF_MASK, rpstat);
2095c349dbc7Sjsg 	else if (IS_HASWELL(i915) || IS_BROADWELL(i915))
2096f005ef32Sjsg 		cagf = REG_FIELD_GET(HSW_CAGF_MASK, rpstat);
20975ca02815Sjsg 	else if (GRAPHICS_VER(i915) >= 6)
2098f005ef32Sjsg 		cagf = REG_FIELD_GET(GEN6_CAGF_MASK, rpstat);
20995ca02815Sjsg 	else
2100f005ef32Sjsg 		cagf = gen5_invert_freq(rps, REG_FIELD_GET(MEMSTAT_PSTATE_MASK, rpstat));
2101c349dbc7Sjsg 
2102c349dbc7Sjsg 	return cagf;
2103c349dbc7Sjsg }
2104c349dbc7Sjsg 
2105f005ef32Sjsg static u32 __read_cagf(struct intel_rps *rps, bool take_fw)
2106c349dbc7Sjsg {
2107c349dbc7Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
21085ca02815Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
2109f005ef32Sjsg 	i915_reg_t r = INVALID_MMIO_REG;
2110c349dbc7Sjsg 	u32 freq;
2111c349dbc7Sjsg 
2112f005ef32Sjsg 	/*
2113f005ef32Sjsg 	 * For Gen12+ reading freq from HW does not need a forcewake and
2114f005ef32Sjsg 	 * registers will return 0 freq when GT is in RC6
2115f005ef32Sjsg 	 */
2116f005ef32Sjsg 	if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)) {
2117f005ef32Sjsg 		r = MTL_MIRROR_TARGET_WP1;
2118f005ef32Sjsg 	} else if (GRAPHICS_VER(i915) >= 12) {
2119f005ef32Sjsg 		r = GEN12_RPSTAT1;
2120f005ef32Sjsg 	} else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
2121c349dbc7Sjsg 		vlv_punit_get(i915);
2122c349dbc7Sjsg 		freq = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);
2123c349dbc7Sjsg 		vlv_punit_put(i915);
21245ca02815Sjsg 	} else if (GRAPHICS_VER(i915) >= 6) {
2125f005ef32Sjsg 		r = GEN6_RPSTAT1;
2126c349dbc7Sjsg 	} else {
2127f005ef32Sjsg 		r = MEMSTAT_ILK;
2128c349dbc7Sjsg 	}
2129c349dbc7Sjsg 
2130f005ef32Sjsg 	if (i915_mmio_reg_valid(r))
2131f005ef32Sjsg 		freq = take_fw ? intel_uncore_read(uncore, r) : intel_uncore_read_fw(uncore, r);
2132f005ef32Sjsg 
2133c349dbc7Sjsg 	return intel_rps_get_cagf(rps, freq);
2134c349dbc7Sjsg }
2135c349dbc7Sjsg 
2136f005ef32Sjsg static u32 read_cagf(struct intel_rps *rps)
2137f005ef32Sjsg {
2138f005ef32Sjsg 	return __read_cagf(rps, true);
2139f005ef32Sjsg }
2140f005ef32Sjsg 
2141c349dbc7Sjsg u32 intel_rps_read_actual_frequency(struct intel_rps *rps)
2142c349dbc7Sjsg {
2143ad8b1aafSjsg 	struct intel_runtime_pm *rpm = rps_to_uncore(rps)->rpm;
2144c349dbc7Sjsg 	intel_wakeref_t wakeref;
2145c349dbc7Sjsg 	u32 freq = 0;
2146c349dbc7Sjsg 
2147c349dbc7Sjsg 	with_intel_runtime_pm_if_in_use(rpm, wakeref)
2148c349dbc7Sjsg 		freq = intel_gpu_freq(rps, read_cagf(rps));
2149c349dbc7Sjsg 
2150c349dbc7Sjsg 	return freq;
2151c349dbc7Sjsg }
2152c349dbc7Sjsg 
2153f005ef32Sjsg u32 intel_rps_read_actual_frequency_fw(struct intel_rps *rps)
2154f005ef32Sjsg {
2155f005ef32Sjsg 	return intel_gpu_freq(rps, __read_cagf(rps, false));
2156f005ef32Sjsg }
2157f005ef32Sjsg 
2158f005ef32Sjsg static u32 intel_rps_read_punit_req(struct intel_rps *rps)
21595ca02815Sjsg {
21605ca02815Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
21615ca02815Sjsg 	struct intel_runtime_pm *rpm = rps_to_uncore(rps)->rpm;
21625ca02815Sjsg 	intel_wakeref_t wakeref;
21635ca02815Sjsg 	u32 freq = 0;
21645ca02815Sjsg 
21655ca02815Sjsg 	with_intel_runtime_pm_if_in_use(rpm, wakeref)
21665ca02815Sjsg 		freq = intel_uncore_read(uncore, GEN6_RPNSWREQ);
21675ca02815Sjsg 
21685ca02815Sjsg 	return freq;
21695ca02815Sjsg }
21705ca02815Sjsg 
21715ca02815Sjsg static u32 intel_rps_get_req(u32 pureq)
21725ca02815Sjsg {
21735ca02815Sjsg 	u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT;
21745ca02815Sjsg 
21755ca02815Sjsg 	return req;
21765ca02815Sjsg }
21775ca02815Sjsg 
21785ca02815Sjsg u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
21795ca02815Sjsg {
21805ca02815Sjsg 	u32 freq = intel_rps_get_req(intel_rps_read_punit_req(rps));
21815ca02815Sjsg 
21825ca02815Sjsg 	return intel_gpu_freq(rps, freq);
21835ca02815Sjsg }
21845ca02815Sjsg 
21855ca02815Sjsg u32 intel_rps_get_requested_frequency(struct intel_rps *rps)
21865ca02815Sjsg {
21875ca02815Sjsg 	if (rps_uses_slpc(rps))
21885ca02815Sjsg 		return intel_rps_read_punit_req_frequency(rps);
21895ca02815Sjsg 	else
21905ca02815Sjsg 		return intel_gpu_freq(rps, rps->cur_freq);
21915ca02815Sjsg }
21925ca02815Sjsg 
21935ca02815Sjsg u32 intel_rps_get_max_frequency(struct intel_rps *rps)
21945ca02815Sjsg {
21955ca02815Sjsg 	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
21965ca02815Sjsg 
21975ca02815Sjsg 	if (rps_uses_slpc(rps))
21985ca02815Sjsg 		return slpc->max_freq_softlimit;
21995ca02815Sjsg 	else
22005ca02815Sjsg 		return intel_gpu_freq(rps, rps->max_freq_softlimit);
22015ca02815Sjsg }
22025ca02815Sjsg 
22031bb76ff1Sjsg /**
22041bb76ff1Sjsg  * intel_rps_get_max_raw_freq - returns the max frequency in some raw format.
22051bb76ff1Sjsg  * @rps: the intel_rps structure
22061bb76ff1Sjsg  *
22071bb76ff1Sjsg  * Returns the max frequency in a raw format. In newer platforms raw is in
22081bb76ff1Sjsg  * units of 50 MHz.
22091bb76ff1Sjsg  */
22101bb76ff1Sjsg u32 intel_rps_get_max_raw_freq(struct intel_rps *rps)
22111bb76ff1Sjsg {
22121bb76ff1Sjsg 	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
22131bb76ff1Sjsg 	u32 freq;
22141bb76ff1Sjsg 
22151bb76ff1Sjsg 	if (rps_uses_slpc(rps)) {
22161bb76ff1Sjsg 		return DIV_ROUND_CLOSEST(slpc->rp0_freq,
22171bb76ff1Sjsg 					 GT_FREQUENCY_MULTIPLIER);
22181bb76ff1Sjsg 	} else {
22191bb76ff1Sjsg 		freq = rps->max_freq;
22201bb76ff1Sjsg 		if (GRAPHICS_VER(rps_to_i915(rps)) >= 9) {
22211bb76ff1Sjsg 			/* Convert GT frequency to 50 MHz units */
22221bb76ff1Sjsg 			freq /= GEN9_FREQ_SCALER;
22231bb76ff1Sjsg 		}
22241bb76ff1Sjsg 		return freq;
22251bb76ff1Sjsg 	}
22261bb76ff1Sjsg }
22271bb76ff1Sjsg 
22285ca02815Sjsg u32 intel_rps_get_rp0_frequency(struct intel_rps *rps)
22295ca02815Sjsg {
22305ca02815Sjsg 	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
22315ca02815Sjsg 
22325ca02815Sjsg 	if (rps_uses_slpc(rps))
22335ca02815Sjsg 		return slpc->rp0_freq;
22345ca02815Sjsg 	else
22355ca02815Sjsg 		return intel_gpu_freq(rps, rps->rp0_freq);
22365ca02815Sjsg }
22375ca02815Sjsg 
22385ca02815Sjsg u32 intel_rps_get_rp1_frequency(struct intel_rps *rps)
22395ca02815Sjsg {
22405ca02815Sjsg 	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
22415ca02815Sjsg 
22425ca02815Sjsg 	if (rps_uses_slpc(rps))
22435ca02815Sjsg 		return slpc->rp1_freq;
22445ca02815Sjsg 	else
22455ca02815Sjsg 		return intel_gpu_freq(rps, rps->rp1_freq);
22465ca02815Sjsg }
22475ca02815Sjsg 
22485ca02815Sjsg u32 intel_rps_get_rpn_frequency(struct intel_rps *rps)
22495ca02815Sjsg {
22505ca02815Sjsg 	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
22515ca02815Sjsg 
22525ca02815Sjsg 	if (rps_uses_slpc(rps))
22535ca02815Sjsg 		return slpc->min_freq;
22545ca02815Sjsg 	else
22555ca02815Sjsg 		return intel_gpu_freq(rps, rps->min_freq);
22565ca02815Sjsg }
22575ca02815Sjsg 
2258f005ef32Sjsg static void rps_frequency_dump(struct intel_rps *rps, struct drm_printer *p)
2259f005ef32Sjsg {
2260f005ef32Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
2261f005ef32Sjsg 	struct drm_i915_private *i915 = gt->i915;
2262f005ef32Sjsg 	struct intel_uncore *uncore = gt->uncore;
2263f005ef32Sjsg 	struct intel_rps_freq_caps caps;
2264f005ef32Sjsg 	u32 rp_state_limits;
2265f005ef32Sjsg 	u32 gt_perf_status;
2266f005ef32Sjsg 	u32 rpmodectl, rpinclimit, rpdeclimit;
2267f005ef32Sjsg 	u32 rpstat, cagf, reqf;
2268f005ef32Sjsg 	u32 rpcurupei, rpcurup, rpprevup;
2269f005ef32Sjsg 	u32 rpcurdownei, rpcurdown, rpprevdown;
2270f005ef32Sjsg 	u32 rpupei, rpupt, rpdownei, rpdownt;
2271f005ef32Sjsg 	u32 pm_ier, pm_imr, pm_isr, pm_iir, pm_mask;
2272f005ef32Sjsg 
2273f005ef32Sjsg 	rp_state_limits = intel_uncore_read(uncore, GEN6_RP_STATE_LIMITS);
2274f005ef32Sjsg 	gen6_rps_get_freq_caps(rps, &caps);
2275f005ef32Sjsg 	if (IS_GEN9_LP(i915))
2276f005ef32Sjsg 		gt_perf_status = intel_uncore_read(uncore, BXT_GT_PERF_STATUS);
2277f005ef32Sjsg 	else
2278f005ef32Sjsg 		gt_perf_status = intel_uncore_read(uncore, GEN6_GT_PERF_STATUS);
2279f005ef32Sjsg 
2280f005ef32Sjsg 	/* RPSTAT1 is in the GT power well */
2281f005ef32Sjsg 	intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
2282f005ef32Sjsg 
2283f005ef32Sjsg 	reqf = intel_uncore_read(uncore, GEN6_RPNSWREQ);
2284f005ef32Sjsg 	if (GRAPHICS_VER(i915) >= 9) {
2285f005ef32Sjsg 		reqf >>= 23;
2286f005ef32Sjsg 	} else {
2287f005ef32Sjsg 		reqf &= ~GEN6_TURBO_DISABLE;
2288f005ef32Sjsg 		if (IS_HASWELL(i915) || IS_BROADWELL(i915))
2289f005ef32Sjsg 			reqf >>= 24;
2290f005ef32Sjsg 		else
2291f005ef32Sjsg 			reqf >>= 25;
2292f005ef32Sjsg 	}
2293f005ef32Sjsg 	reqf = intel_gpu_freq(rps, reqf);
2294f005ef32Sjsg 
2295f005ef32Sjsg 	rpmodectl = intel_uncore_read(uncore, GEN6_RP_CONTROL);
2296f005ef32Sjsg 	rpinclimit = intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD);
2297f005ef32Sjsg 	rpdeclimit = intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD);
2298f005ef32Sjsg 
2299f005ef32Sjsg 	rpstat = intel_rps_read_rpstat(rps);
2300f005ef32Sjsg 	rpcurupei = intel_uncore_read(uncore, GEN6_RP_CUR_UP_EI) & GEN6_CURICONT_MASK;
2301f005ef32Sjsg 	rpcurup = intel_uncore_read(uncore, GEN6_RP_CUR_UP) & GEN6_CURBSYTAVG_MASK;
2302f005ef32Sjsg 	rpprevup = intel_uncore_read(uncore, GEN6_RP_PREV_UP) & GEN6_CURBSYTAVG_MASK;
2303f005ef32Sjsg 	rpcurdownei = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK;
2304f005ef32Sjsg 	rpcurdown = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK;
2305f005ef32Sjsg 	rpprevdown = intel_uncore_read(uncore, GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK;
2306f005ef32Sjsg 
2307f005ef32Sjsg 	rpupei = intel_uncore_read(uncore, GEN6_RP_UP_EI);
2308f005ef32Sjsg 	rpupt = intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD);
2309f005ef32Sjsg 
2310f005ef32Sjsg 	rpdownei = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
2311f005ef32Sjsg 	rpdownt = intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD);
2312f005ef32Sjsg 
2313f005ef32Sjsg 	cagf = intel_rps_read_actual_frequency(rps);
2314f005ef32Sjsg 
2315f005ef32Sjsg 	intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
2316f005ef32Sjsg 
2317f005ef32Sjsg 	if (GRAPHICS_VER(i915) >= 11) {
2318f005ef32Sjsg 		pm_ier = intel_uncore_read(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE);
2319f005ef32Sjsg 		pm_imr = intel_uncore_read(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK);
2320f005ef32Sjsg 		/*
2321f005ef32Sjsg 		 * The equivalent to the PM ISR & IIR cannot be read
2322f005ef32Sjsg 		 * without affecting the current state of the system
2323f005ef32Sjsg 		 */
2324f005ef32Sjsg 		pm_isr = 0;
2325f005ef32Sjsg 		pm_iir = 0;
2326f005ef32Sjsg 	} else if (GRAPHICS_VER(i915) >= 8) {
2327f005ef32Sjsg 		pm_ier = intel_uncore_read(uncore, GEN8_GT_IER(2));
2328f005ef32Sjsg 		pm_imr = intel_uncore_read(uncore, GEN8_GT_IMR(2));
2329f005ef32Sjsg 		pm_isr = intel_uncore_read(uncore, GEN8_GT_ISR(2));
2330f005ef32Sjsg 		pm_iir = intel_uncore_read(uncore, GEN8_GT_IIR(2));
2331f005ef32Sjsg 	} else {
2332f005ef32Sjsg 		pm_ier = intel_uncore_read(uncore, GEN6_PMIER);
2333f005ef32Sjsg 		pm_imr = intel_uncore_read(uncore, GEN6_PMIMR);
2334f005ef32Sjsg 		pm_isr = intel_uncore_read(uncore, GEN6_PMISR);
2335f005ef32Sjsg 		pm_iir = intel_uncore_read(uncore, GEN6_PMIIR);
2336f005ef32Sjsg 	}
2337f005ef32Sjsg 	pm_mask = intel_uncore_read(uncore, GEN6_PMINTRMSK);
2338f005ef32Sjsg 
2339f005ef32Sjsg 	drm_printf(p, "Video Turbo Mode: %s\n",
2340f005ef32Sjsg 		   str_yes_no(rpmodectl & GEN6_RP_MEDIA_TURBO));
2341f005ef32Sjsg 	drm_printf(p, "HW control enabled: %s\n",
2342f005ef32Sjsg 		   str_yes_no(rpmodectl & GEN6_RP_ENABLE));
2343f005ef32Sjsg 	drm_printf(p, "SW control enabled: %s\n",
2344f005ef32Sjsg 		   str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE));
2345f005ef32Sjsg 
2346f005ef32Sjsg 	drm_printf(p, "PM IER=0x%08x IMR=0x%08x, MASK=0x%08x\n",
2347f005ef32Sjsg 		   pm_ier, pm_imr, pm_mask);
2348f005ef32Sjsg 	if (GRAPHICS_VER(i915) <= 10)
2349f005ef32Sjsg 		drm_printf(p, "PM ISR=0x%08x IIR=0x%08x\n",
2350f005ef32Sjsg 			   pm_isr, pm_iir);
2351f005ef32Sjsg 	drm_printf(p, "pm_intrmsk_mbz: 0x%08x\n",
2352f005ef32Sjsg 		   rps->pm_intrmsk_mbz);
2353f005ef32Sjsg 	drm_printf(p, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
2354f005ef32Sjsg 	drm_printf(p, "Render p-state ratio: %d\n",
2355f005ef32Sjsg 		   (gt_perf_status & (GRAPHICS_VER(i915) >= 9 ? 0x1ff00 : 0xff00)) >> 8);
2356f005ef32Sjsg 	drm_printf(p, "Render p-state VID: %d\n",
2357f005ef32Sjsg 		   gt_perf_status & 0xff);
2358f005ef32Sjsg 	drm_printf(p, "Render p-state limit: %d\n",
2359f005ef32Sjsg 		   rp_state_limits & 0xff);
2360f005ef32Sjsg 	drm_printf(p, "RPSTAT1: 0x%08x\n", rpstat);
2361f005ef32Sjsg 	drm_printf(p, "RPMODECTL: 0x%08x\n", rpmodectl);
2362f005ef32Sjsg 	drm_printf(p, "RPINCLIMIT: 0x%08x\n", rpinclimit);
2363f005ef32Sjsg 	drm_printf(p, "RPDECLIMIT: 0x%08x\n", rpdeclimit);
2364f005ef32Sjsg 	drm_printf(p, "RPNSWREQ: %dMHz\n", reqf);
2365f005ef32Sjsg 	drm_printf(p, "CAGF: %dMHz\n", cagf);
2366f005ef32Sjsg 	drm_printf(p, "RP CUR UP EI: %d (%lldns)\n",
2367f005ef32Sjsg 		   rpcurupei,
2368f005ef32Sjsg 		   intel_gt_pm_interval_to_ns(gt, rpcurupei));
2369f005ef32Sjsg 	drm_printf(p, "RP CUR UP: %d (%lldns)\n",
2370f005ef32Sjsg 		   rpcurup, intel_gt_pm_interval_to_ns(gt, rpcurup));
2371f005ef32Sjsg 	drm_printf(p, "RP PREV UP: %d (%lldns)\n",
2372f005ef32Sjsg 		   rpprevup, intel_gt_pm_interval_to_ns(gt, rpprevup));
2373f005ef32Sjsg 	drm_printf(p, "Up threshold: %d%%\n",
2374f005ef32Sjsg 		   rps->power.up_threshold);
2375f005ef32Sjsg 	drm_printf(p, "RP UP EI: %d (%lldns)\n",
2376f005ef32Sjsg 		   rpupei, intel_gt_pm_interval_to_ns(gt, rpupei));
2377f005ef32Sjsg 	drm_printf(p, "RP UP THRESHOLD: %d (%lldns)\n",
2378f005ef32Sjsg 		   rpupt, intel_gt_pm_interval_to_ns(gt, rpupt));
2379f005ef32Sjsg 
2380f005ef32Sjsg 	drm_printf(p, "RP CUR DOWN EI: %d (%lldns)\n",
2381f005ef32Sjsg 		   rpcurdownei,
2382f005ef32Sjsg 		   intel_gt_pm_interval_to_ns(gt, rpcurdownei));
2383f005ef32Sjsg 	drm_printf(p, "RP CUR DOWN: %d (%lldns)\n",
2384f005ef32Sjsg 		   rpcurdown,
2385f005ef32Sjsg 		   intel_gt_pm_interval_to_ns(gt, rpcurdown));
2386f005ef32Sjsg 	drm_printf(p, "RP PREV DOWN: %d (%lldns)\n",
2387f005ef32Sjsg 		   rpprevdown,
2388f005ef32Sjsg 		   intel_gt_pm_interval_to_ns(gt, rpprevdown));
2389f005ef32Sjsg 	drm_printf(p, "Down threshold: %d%%\n",
2390f005ef32Sjsg 		   rps->power.down_threshold);
2391f005ef32Sjsg 	drm_printf(p, "RP DOWN EI: %d (%lldns)\n",
2392f005ef32Sjsg 		   rpdownei, intel_gt_pm_interval_to_ns(gt, rpdownei));
2393f005ef32Sjsg 	drm_printf(p, "RP DOWN THRESHOLD: %d (%lldns)\n",
2394f005ef32Sjsg 		   rpdownt, intel_gt_pm_interval_to_ns(gt, rpdownt));
2395f005ef32Sjsg 
2396f005ef32Sjsg 	drm_printf(p, "Lowest (RPN) frequency: %dMHz\n",
2397f005ef32Sjsg 		   intel_gpu_freq(rps, caps.min_freq));
2398f005ef32Sjsg 	drm_printf(p, "Nominal (RP1) frequency: %dMHz\n",
2399f005ef32Sjsg 		   intel_gpu_freq(rps, caps.rp1_freq));
2400f005ef32Sjsg 	drm_printf(p, "Max non-overclocked (RP0) frequency: %dMHz\n",
2401f005ef32Sjsg 		   intel_gpu_freq(rps, caps.rp0_freq));
2402f005ef32Sjsg 	drm_printf(p, "Max overclocked frequency: %dMHz\n",
2403f005ef32Sjsg 		   intel_gpu_freq(rps, rps->max_freq));
2404f005ef32Sjsg 
2405f005ef32Sjsg 	drm_printf(p, "Current freq: %d MHz\n",
2406f005ef32Sjsg 		   intel_gpu_freq(rps, rps->cur_freq));
2407f005ef32Sjsg 	drm_printf(p, "Actual freq: %d MHz\n", cagf);
2408f005ef32Sjsg 	drm_printf(p, "Idle freq: %d MHz\n",
2409f005ef32Sjsg 		   intel_gpu_freq(rps, rps->idle_freq));
2410f005ef32Sjsg 	drm_printf(p, "Min freq: %d MHz\n",
2411f005ef32Sjsg 		   intel_gpu_freq(rps, rps->min_freq));
2412f005ef32Sjsg 	drm_printf(p, "Boost freq: %d MHz\n",
2413f005ef32Sjsg 		   intel_gpu_freq(rps, rps->boost_freq));
2414f005ef32Sjsg 	drm_printf(p, "Max freq: %d MHz\n",
2415f005ef32Sjsg 		   intel_gpu_freq(rps, rps->max_freq));
2416f005ef32Sjsg 	drm_printf(p,
2417f005ef32Sjsg 		   "efficient (RPe) frequency: %d MHz\n",
2418f005ef32Sjsg 		   intel_gpu_freq(rps, rps->efficient_freq));
2419f005ef32Sjsg }
2420f005ef32Sjsg 
2421f005ef32Sjsg static void slpc_frequency_dump(struct intel_rps *rps, struct drm_printer *p)
2422f005ef32Sjsg {
2423f005ef32Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
2424f005ef32Sjsg 	struct intel_uncore *uncore = gt->uncore;
2425f005ef32Sjsg 	struct intel_rps_freq_caps caps;
2426f005ef32Sjsg 	u32 pm_mask;
2427f005ef32Sjsg 
2428f005ef32Sjsg 	gen6_rps_get_freq_caps(rps, &caps);
2429f005ef32Sjsg 	pm_mask = intel_uncore_read(uncore, GEN6_PMINTRMSK);
2430f005ef32Sjsg 
2431f005ef32Sjsg 	drm_printf(p, "PM MASK=0x%08x\n", pm_mask);
2432f005ef32Sjsg 	drm_printf(p, "pm_intrmsk_mbz: 0x%08x\n",
2433f005ef32Sjsg 		   rps->pm_intrmsk_mbz);
2434f005ef32Sjsg 	drm_printf(p, "RPSTAT1: 0x%08x\n", intel_rps_read_rpstat(rps));
2435f005ef32Sjsg 	drm_printf(p, "RPNSWREQ: %dMHz\n", intel_rps_get_requested_frequency(rps));
2436f005ef32Sjsg 	drm_printf(p, "Lowest (RPN) frequency: %dMHz\n",
2437f005ef32Sjsg 		   intel_gpu_freq(rps, caps.min_freq));
2438f005ef32Sjsg 	drm_printf(p, "Nominal (RP1) frequency: %dMHz\n",
2439f005ef32Sjsg 		   intel_gpu_freq(rps, caps.rp1_freq));
2440f005ef32Sjsg 	drm_printf(p, "Max non-overclocked (RP0) frequency: %dMHz\n",
2441f005ef32Sjsg 		   intel_gpu_freq(rps, caps.rp0_freq));
2442f005ef32Sjsg 	drm_printf(p, "Current freq: %d MHz\n",
2443f005ef32Sjsg 		   intel_rps_get_requested_frequency(rps));
2444f005ef32Sjsg 	drm_printf(p, "Actual freq: %d MHz\n",
2445f005ef32Sjsg 		   intel_rps_read_actual_frequency(rps));
2446f005ef32Sjsg 	drm_printf(p, "Min freq: %d MHz\n",
2447f005ef32Sjsg 		   intel_rps_get_min_frequency(rps));
2448f005ef32Sjsg 	drm_printf(p, "Boost freq: %d MHz\n",
2449f005ef32Sjsg 		   intel_rps_get_boost_frequency(rps));
2450f005ef32Sjsg 	drm_printf(p, "Max freq: %d MHz\n",
2451f005ef32Sjsg 		   intel_rps_get_max_frequency(rps));
2452f005ef32Sjsg 	drm_printf(p,
2453f005ef32Sjsg 		   "efficient (RPe) frequency: %d MHz\n",
2454f005ef32Sjsg 		   intel_gpu_freq(rps, caps.rp1_freq));
2455f005ef32Sjsg }
2456f005ef32Sjsg 
2457f005ef32Sjsg void gen6_rps_frequency_dump(struct intel_rps *rps, struct drm_printer *p)
2458f005ef32Sjsg {
2459f005ef32Sjsg 	if (rps_uses_slpc(rps))
2460f005ef32Sjsg 		return slpc_frequency_dump(rps, p);
2461f005ef32Sjsg 	else
2462f005ef32Sjsg 		return rps_frequency_dump(rps, p);
2463f005ef32Sjsg }
2464f005ef32Sjsg 
24655ca02815Sjsg static int set_max_freq(struct intel_rps *rps, u32 val)
24665ca02815Sjsg {
24675ca02815Sjsg 	struct drm_i915_private *i915 = rps_to_i915(rps);
24685ca02815Sjsg 	int ret = 0;
24695ca02815Sjsg 
24705ca02815Sjsg 	mutex_lock(&rps->lock);
24715ca02815Sjsg 
24725ca02815Sjsg 	val = intel_freq_opcode(rps, val);
24735ca02815Sjsg 	if (val < rps->min_freq ||
24745ca02815Sjsg 	    val > rps->max_freq ||
24755ca02815Sjsg 	    val < rps->min_freq_softlimit) {
24765ca02815Sjsg 		ret = -EINVAL;
24775ca02815Sjsg 		goto unlock;
24785ca02815Sjsg 	}
24795ca02815Sjsg 
24805ca02815Sjsg 	if (val > rps->rp0_freq)
24815ca02815Sjsg 		drm_dbg(&i915->drm, "User requested overclocking to %d\n",
24825ca02815Sjsg 			intel_gpu_freq(rps, val));
24835ca02815Sjsg 
24845ca02815Sjsg 	rps->max_freq_softlimit = val;
24855ca02815Sjsg 
24865ca02815Sjsg 	val = clamp_t(int, rps->cur_freq,
24875ca02815Sjsg 		      rps->min_freq_softlimit,
24885ca02815Sjsg 		      rps->max_freq_softlimit);
24895ca02815Sjsg 
24905ca02815Sjsg 	/*
24915ca02815Sjsg 	 * We still need *_set_rps to process the new max_delay and
24925ca02815Sjsg 	 * update the interrupt limits and PMINTRMSK even though
24935ca02815Sjsg 	 * frequency request may be unchanged.
24945ca02815Sjsg 	 */
24955ca02815Sjsg 	intel_rps_set(rps, val);
24965ca02815Sjsg 
24975ca02815Sjsg unlock:
24985ca02815Sjsg 	mutex_unlock(&rps->lock);
24995ca02815Sjsg 
25005ca02815Sjsg 	return ret;
25015ca02815Sjsg }
25025ca02815Sjsg 
25035ca02815Sjsg int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val)
25045ca02815Sjsg {
25055ca02815Sjsg 	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
25065ca02815Sjsg 
25075ca02815Sjsg 	if (rps_uses_slpc(rps))
25085ca02815Sjsg 		return intel_guc_slpc_set_max_freq(slpc, val);
25095ca02815Sjsg 	else
25105ca02815Sjsg 		return set_max_freq(rps, val);
25115ca02815Sjsg }
25125ca02815Sjsg 
25135ca02815Sjsg u32 intel_rps_get_min_frequency(struct intel_rps *rps)
25145ca02815Sjsg {
25155ca02815Sjsg 	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
25165ca02815Sjsg 
25175ca02815Sjsg 	if (rps_uses_slpc(rps))
25185ca02815Sjsg 		return slpc->min_freq_softlimit;
25195ca02815Sjsg 	else
25205ca02815Sjsg 		return intel_gpu_freq(rps, rps->min_freq_softlimit);
25215ca02815Sjsg }
25225ca02815Sjsg 
25231bb76ff1Sjsg /**
25241bb76ff1Sjsg  * intel_rps_get_min_raw_freq - returns the min frequency in some raw format.
25251bb76ff1Sjsg  * @rps: the intel_rps structure
25261bb76ff1Sjsg  *
25271bb76ff1Sjsg  * Returns the min frequency in a raw format. In newer platforms raw is in
25281bb76ff1Sjsg  * units of 50 MHz.
25291bb76ff1Sjsg  */
25301bb76ff1Sjsg u32 intel_rps_get_min_raw_freq(struct intel_rps *rps)
25311bb76ff1Sjsg {
25321bb76ff1Sjsg 	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
25331bb76ff1Sjsg 	u32 freq;
25341bb76ff1Sjsg 
25351bb76ff1Sjsg 	if (rps_uses_slpc(rps)) {
25361bb76ff1Sjsg 		return DIV_ROUND_CLOSEST(slpc->min_freq,
25371bb76ff1Sjsg 					 GT_FREQUENCY_MULTIPLIER);
25381bb76ff1Sjsg 	} else {
25391bb76ff1Sjsg 		freq = rps->min_freq;
25401bb76ff1Sjsg 		if (GRAPHICS_VER(rps_to_i915(rps)) >= 9) {
25411bb76ff1Sjsg 			/* Convert GT frequency to 50 MHz units */
25421bb76ff1Sjsg 			freq /= GEN9_FREQ_SCALER;
25431bb76ff1Sjsg 		}
25441bb76ff1Sjsg 		return freq;
25451bb76ff1Sjsg 	}
25461bb76ff1Sjsg }
25471bb76ff1Sjsg 
25485ca02815Sjsg static int set_min_freq(struct intel_rps *rps, u32 val)
25495ca02815Sjsg {
25505ca02815Sjsg 	int ret = 0;
25515ca02815Sjsg 
25525ca02815Sjsg 	mutex_lock(&rps->lock);
25535ca02815Sjsg 
25545ca02815Sjsg 	val = intel_freq_opcode(rps, val);
25555ca02815Sjsg 	if (val < rps->min_freq ||
25565ca02815Sjsg 	    val > rps->max_freq ||
25575ca02815Sjsg 	    val > rps->max_freq_softlimit) {
25585ca02815Sjsg 		ret = -EINVAL;
25595ca02815Sjsg 		goto unlock;
25605ca02815Sjsg 	}
25615ca02815Sjsg 
25625ca02815Sjsg 	rps->min_freq_softlimit = val;
25635ca02815Sjsg 
25645ca02815Sjsg 	val = clamp_t(int, rps->cur_freq,
25655ca02815Sjsg 		      rps->min_freq_softlimit,
25665ca02815Sjsg 		      rps->max_freq_softlimit);
25675ca02815Sjsg 
25685ca02815Sjsg 	/*
25695ca02815Sjsg 	 * We still need *_set_rps to process the new min_delay and
25705ca02815Sjsg 	 * update the interrupt limits and PMINTRMSK even though
25715ca02815Sjsg 	 * frequency request may be unchanged.
25725ca02815Sjsg 	 */
25735ca02815Sjsg 	intel_rps_set(rps, val);
25745ca02815Sjsg 
25755ca02815Sjsg unlock:
25765ca02815Sjsg 	mutex_unlock(&rps->lock);
25775ca02815Sjsg 
25785ca02815Sjsg 	return ret;
25795ca02815Sjsg }
25805ca02815Sjsg 
25815ca02815Sjsg int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val)
25825ca02815Sjsg {
25835ca02815Sjsg 	struct intel_guc_slpc *slpc = rps_to_slpc(rps);
25845ca02815Sjsg 
25855ca02815Sjsg 	if (rps_uses_slpc(rps))
25865ca02815Sjsg 		return intel_guc_slpc_set_min_freq(slpc, val);
25875ca02815Sjsg 	else
25885ca02815Sjsg 		return set_min_freq(rps, val);
25895ca02815Sjsg }
25905ca02815Sjsg 
2591f005ef32Sjsg u8 intel_rps_get_up_threshold(struct intel_rps *rps)
2592f005ef32Sjsg {
2593f005ef32Sjsg 	return rps->power.up_threshold;
2594f005ef32Sjsg }
2595f005ef32Sjsg 
2596f005ef32Sjsg static int rps_set_threshold(struct intel_rps *rps, u8 *threshold, u8 val)
2597f005ef32Sjsg {
2598f005ef32Sjsg 	int ret;
2599f005ef32Sjsg 
2600f005ef32Sjsg 	if (val > 100)
2601f005ef32Sjsg 		return -EINVAL;
2602f005ef32Sjsg 
2603f005ef32Sjsg 	ret = mutex_lock_interruptible(&rps->lock);
2604f005ef32Sjsg 	if (ret)
2605f005ef32Sjsg 		return ret;
2606f005ef32Sjsg 
2607f005ef32Sjsg 	if (*threshold == val)
2608f005ef32Sjsg 		goto out_unlock;
2609f005ef32Sjsg 
2610f005ef32Sjsg 	*threshold = val;
2611f005ef32Sjsg 
2612f005ef32Sjsg 	/* Force reset. */
2613f005ef32Sjsg 	rps->last_freq = -1;
2614f005ef32Sjsg 	mutex_lock(&rps->power.mutex);
2615f005ef32Sjsg 	rps->power.mode = -1;
2616f005ef32Sjsg 	mutex_unlock(&rps->power.mutex);
2617f005ef32Sjsg 
2618f005ef32Sjsg 	intel_rps_set(rps, clamp(rps->cur_freq,
2619f005ef32Sjsg 				 rps->min_freq_softlimit,
2620f005ef32Sjsg 				 rps->max_freq_softlimit));
2621f005ef32Sjsg 
2622f005ef32Sjsg out_unlock:
2623f005ef32Sjsg 	mutex_unlock(&rps->lock);
2624f005ef32Sjsg 
2625f005ef32Sjsg 	return ret;
2626f005ef32Sjsg }
2627f005ef32Sjsg 
2628f005ef32Sjsg int intel_rps_set_up_threshold(struct intel_rps *rps, u8 threshold)
2629f005ef32Sjsg {
2630f005ef32Sjsg 	return rps_set_threshold(rps, &rps->power.up_threshold, threshold);
2631f005ef32Sjsg }
2632f005ef32Sjsg 
2633f005ef32Sjsg u8 intel_rps_get_down_threshold(struct intel_rps *rps)
2634f005ef32Sjsg {
2635f005ef32Sjsg 	return rps->power.down_threshold;
2636f005ef32Sjsg }
2637f005ef32Sjsg 
2638f005ef32Sjsg int intel_rps_set_down_threshold(struct intel_rps *rps, u8 threshold)
2639f005ef32Sjsg {
2640f005ef32Sjsg 	return rps_set_threshold(rps, &rps->power.down_threshold, threshold);
2641f005ef32Sjsg }
2642f005ef32Sjsg 
26431bb76ff1Sjsg static void intel_rps_set_manual(struct intel_rps *rps, bool enable)
26441bb76ff1Sjsg {
26451bb76ff1Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
26461bb76ff1Sjsg 	u32 state = enable ? GEN9_RPSWCTL_ENABLE : GEN9_RPSWCTL_DISABLE;
26471bb76ff1Sjsg 
26481bb76ff1Sjsg 	/* Allow punit to process software requests */
26491bb76ff1Sjsg 	intel_uncore_write(uncore, GEN6_RP_CONTROL, state);
26501bb76ff1Sjsg }
26511bb76ff1Sjsg 
26521bb76ff1Sjsg void intel_rps_raise_unslice(struct intel_rps *rps)
26531bb76ff1Sjsg {
26541bb76ff1Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
26551bb76ff1Sjsg 
26561bb76ff1Sjsg 	mutex_lock(&rps->lock);
26571bb76ff1Sjsg 
26581bb76ff1Sjsg 	if (rps_uses_slpc(rps)) {
26591bb76ff1Sjsg 		/* RP limits have not been initialized yet for SLPC path */
26601bb76ff1Sjsg 		struct intel_rps_freq_caps caps;
26611bb76ff1Sjsg 
26621bb76ff1Sjsg 		gen6_rps_get_freq_caps(rps, &caps);
26631bb76ff1Sjsg 
26641bb76ff1Sjsg 		intel_rps_set_manual(rps, true);
26651bb76ff1Sjsg 		intel_uncore_write(uncore, GEN6_RPNSWREQ,
26661bb76ff1Sjsg 				   ((caps.rp0_freq <<
26671bb76ff1Sjsg 				   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT) |
26681bb76ff1Sjsg 				   GEN9_IGNORE_SLICE_RATIO));
26691bb76ff1Sjsg 		intel_rps_set_manual(rps, false);
26701bb76ff1Sjsg 	} else {
26711bb76ff1Sjsg 		intel_rps_set(rps, rps->rp0_freq);
26721bb76ff1Sjsg 	}
26731bb76ff1Sjsg 
26741bb76ff1Sjsg 	mutex_unlock(&rps->lock);
26751bb76ff1Sjsg }
26761bb76ff1Sjsg 
26771bb76ff1Sjsg void intel_rps_lower_unslice(struct intel_rps *rps)
26781bb76ff1Sjsg {
26791bb76ff1Sjsg 	struct intel_uncore *uncore = rps_to_uncore(rps);
26801bb76ff1Sjsg 
26811bb76ff1Sjsg 	mutex_lock(&rps->lock);
26821bb76ff1Sjsg 
26831bb76ff1Sjsg 	if (rps_uses_slpc(rps)) {
26841bb76ff1Sjsg 		/* RP limits have not been initialized yet for SLPC path */
26851bb76ff1Sjsg 		struct intel_rps_freq_caps caps;
26861bb76ff1Sjsg 
26871bb76ff1Sjsg 		gen6_rps_get_freq_caps(rps, &caps);
26881bb76ff1Sjsg 
26891bb76ff1Sjsg 		intel_rps_set_manual(rps, true);
26901bb76ff1Sjsg 		intel_uncore_write(uncore, GEN6_RPNSWREQ,
26911bb76ff1Sjsg 				   ((caps.min_freq <<
26921bb76ff1Sjsg 				   GEN9_SW_REQ_UNSLICE_RATIO_SHIFT) |
26931bb76ff1Sjsg 				   GEN9_IGNORE_SLICE_RATIO));
26941bb76ff1Sjsg 		intel_rps_set_manual(rps, false);
26951bb76ff1Sjsg 	} else {
26961bb76ff1Sjsg 		intel_rps_set(rps, rps->min_freq);
26971bb76ff1Sjsg 	}
26981bb76ff1Sjsg 
26991bb76ff1Sjsg 	mutex_unlock(&rps->lock);
27001bb76ff1Sjsg }
27011bb76ff1Sjsg 
27021bb76ff1Sjsg static u32 rps_read_mmio(struct intel_rps *rps, i915_reg_t reg32)
27031bb76ff1Sjsg {
27041bb76ff1Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
27051bb76ff1Sjsg 	intel_wakeref_t wakeref;
27061bb76ff1Sjsg 	u32 val;
27071bb76ff1Sjsg 
27081bb76ff1Sjsg 	with_intel_runtime_pm(gt->uncore->rpm, wakeref)
27091bb76ff1Sjsg 		val = intel_uncore_read(gt->uncore, reg32);
27101bb76ff1Sjsg 
27111bb76ff1Sjsg 	return val;
27121bb76ff1Sjsg }
27131bb76ff1Sjsg 
27141bb76ff1Sjsg bool rps_read_mask_mmio(struct intel_rps *rps,
27151bb76ff1Sjsg 			i915_reg_t reg32, u32 mask)
27161bb76ff1Sjsg {
27171bb76ff1Sjsg 	return rps_read_mmio(rps, reg32) & mask;
27181bb76ff1Sjsg }
27191bb76ff1Sjsg 
2720c349dbc7Sjsg /* External interface for intel_ips.ko */
2721c349dbc7Sjsg 
2722c349dbc7Sjsg static struct drm_i915_private __rcu *ips_mchdev;
2723c349dbc7Sjsg 
2724f005ef32Sjsg /*
2725c349dbc7Sjsg  * Tells the intel_ips driver that the i915 driver is now loaded, if
2726c349dbc7Sjsg  * IPS got loaded first.
2727c349dbc7Sjsg  *
2728c349dbc7Sjsg  * This awkward dance is so that neither module has to depend on the
2729c349dbc7Sjsg  * other in order for IPS to do the appropriate communication of
2730c349dbc7Sjsg  * GPU turbo limits to i915.
2731c349dbc7Sjsg  */
2732c349dbc7Sjsg static void
2733c349dbc7Sjsg ips_ping_for_i915_load(void)
2734c349dbc7Sjsg {
2735c349dbc7Sjsg #ifdef __linux__
2736c349dbc7Sjsg 	void (*link)(void);
2737c349dbc7Sjsg 
2738c349dbc7Sjsg 	link = symbol_get(ips_link_to_i915_driver);
2739c349dbc7Sjsg 	if (link) {
2740c349dbc7Sjsg 		link();
2741c349dbc7Sjsg 		symbol_put(ips_link_to_i915_driver);
2742c349dbc7Sjsg 	}
2743c349dbc7Sjsg #endif
2744c349dbc7Sjsg }
2745c349dbc7Sjsg 
2746c349dbc7Sjsg void intel_rps_driver_register(struct intel_rps *rps)
2747c349dbc7Sjsg {
2748c349dbc7Sjsg 	struct intel_gt *gt = rps_to_gt(rps);
2749c349dbc7Sjsg 
2750c349dbc7Sjsg 	/*
2751c349dbc7Sjsg 	 * We only register the i915 ips part with intel-ips once everything is
2752c349dbc7Sjsg 	 * set up, to avoid intel-ips sneaking in and reading bogus values.
2753c349dbc7Sjsg 	 */
27545ca02815Sjsg 	if (GRAPHICS_VER(gt->i915) == 5) {
2755c349dbc7Sjsg 		GEM_BUG_ON(ips_mchdev);
2756c349dbc7Sjsg 		rcu_assign_pointer(ips_mchdev, gt->i915);
2757c349dbc7Sjsg 		ips_ping_for_i915_load();
2758c349dbc7Sjsg 	}
2759c349dbc7Sjsg }
2760c349dbc7Sjsg 
2761c349dbc7Sjsg void intel_rps_driver_unregister(struct intel_rps *rps)
2762c349dbc7Sjsg {
2763c349dbc7Sjsg 	if (rcu_access_pointer(ips_mchdev) == rps_to_i915(rps))
2764c349dbc7Sjsg 		rcu_assign_pointer(ips_mchdev, NULL);
2765c349dbc7Sjsg }
2766c349dbc7Sjsg 
2767c349dbc7Sjsg static struct drm_i915_private *mchdev_get(void)
2768c349dbc7Sjsg {
2769c349dbc7Sjsg 	struct drm_i915_private *i915;
2770c349dbc7Sjsg 
2771c349dbc7Sjsg 	rcu_read_lock();
2772c349dbc7Sjsg 	i915 = rcu_dereference(ips_mchdev);
27735ca02815Sjsg 	if (i915 && !kref_get_unless_zero(&i915->drm.ref))
2774c349dbc7Sjsg 		i915 = NULL;
2775c349dbc7Sjsg 	rcu_read_unlock();
2776c349dbc7Sjsg 
2777c349dbc7Sjsg 	return i915;
2778c349dbc7Sjsg }
2779c349dbc7Sjsg 
2780c349dbc7Sjsg /**
2781c349dbc7Sjsg  * i915_read_mch_val - return value for IPS use
2782c349dbc7Sjsg  *
2783c349dbc7Sjsg  * Calculate and return a value for the IPS driver to use when deciding whether
2784c349dbc7Sjsg  * we have thermal and power headroom to increase CPU or GPU power budget.
2785c349dbc7Sjsg  */
2786c349dbc7Sjsg unsigned long i915_read_mch_val(void)
2787c349dbc7Sjsg {
2788c349dbc7Sjsg 	struct drm_i915_private *i915;
2789c349dbc7Sjsg 	unsigned long chipset_val = 0;
2790c349dbc7Sjsg 	unsigned long graphics_val = 0;
2791c349dbc7Sjsg 	intel_wakeref_t wakeref;
2792c349dbc7Sjsg 
2793c349dbc7Sjsg 	i915 = mchdev_get();
2794c349dbc7Sjsg 	if (!i915)
2795c349dbc7Sjsg 		return 0;
2796c349dbc7Sjsg 
2797c349dbc7Sjsg 	with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
27981bb76ff1Sjsg 		struct intel_ips *ips = &to_gt(i915)->rps.ips;
2799c349dbc7Sjsg 
2800c349dbc7Sjsg 		spin_lock_irq(&mchdev_lock);
2801c349dbc7Sjsg 		chipset_val = __ips_chipset_val(ips);
2802c349dbc7Sjsg 		graphics_val = __ips_gfx_val(ips);
2803c349dbc7Sjsg 		spin_unlock_irq(&mchdev_lock);
2804c349dbc7Sjsg 	}
2805c349dbc7Sjsg 
2806c349dbc7Sjsg 	drm_dev_put(&i915->drm);
2807c349dbc7Sjsg 	return chipset_val + graphics_val;
2808c349dbc7Sjsg }
2809c349dbc7Sjsg EXPORT_SYMBOL_GPL(i915_read_mch_val);
2810c349dbc7Sjsg 
2811c349dbc7Sjsg /**
2812c349dbc7Sjsg  * i915_gpu_raise - raise GPU frequency limit
2813c349dbc7Sjsg  *
2814c349dbc7Sjsg  * Raise the limit; IPS indicates we have thermal headroom.
2815c349dbc7Sjsg  */
2816c349dbc7Sjsg bool i915_gpu_raise(void)
2817c349dbc7Sjsg {
2818c349dbc7Sjsg 	struct drm_i915_private *i915;
2819c349dbc7Sjsg 	struct intel_rps *rps;
2820c349dbc7Sjsg 
2821c349dbc7Sjsg 	i915 = mchdev_get();
2822c349dbc7Sjsg 	if (!i915)
2823c349dbc7Sjsg 		return false;
2824c349dbc7Sjsg 
28251bb76ff1Sjsg 	rps = &to_gt(i915)->rps;
2826c349dbc7Sjsg 
2827c349dbc7Sjsg 	spin_lock_irq(&mchdev_lock);
2828c349dbc7Sjsg 	if (rps->max_freq_softlimit < rps->max_freq)
2829c349dbc7Sjsg 		rps->max_freq_softlimit++;
2830c349dbc7Sjsg 	spin_unlock_irq(&mchdev_lock);
2831c349dbc7Sjsg 
2832c349dbc7Sjsg 	drm_dev_put(&i915->drm);
2833c349dbc7Sjsg 	return true;
2834c349dbc7Sjsg }
2835c349dbc7Sjsg EXPORT_SYMBOL_GPL(i915_gpu_raise);
2836c349dbc7Sjsg 
2837c349dbc7Sjsg /**
2838c349dbc7Sjsg  * i915_gpu_lower - lower GPU frequency limit
2839c349dbc7Sjsg  *
2840c349dbc7Sjsg  * IPS indicates we're close to a thermal limit, so throttle back the GPU
2841c349dbc7Sjsg  * frequency maximum.
2842c349dbc7Sjsg  */
2843c349dbc7Sjsg bool i915_gpu_lower(void)
2844c349dbc7Sjsg {
2845c349dbc7Sjsg 	struct drm_i915_private *i915;
2846c349dbc7Sjsg 	struct intel_rps *rps;
2847c349dbc7Sjsg 
2848c349dbc7Sjsg 	i915 = mchdev_get();
2849c349dbc7Sjsg 	if (!i915)
2850c349dbc7Sjsg 		return false;
2851c349dbc7Sjsg 
28521bb76ff1Sjsg 	rps = &to_gt(i915)->rps;
2853c349dbc7Sjsg 
2854c349dbc7Sjsg 	spin_lock_irq(&mchdev_lock);
2855c349dbc7Sjsg 	if (rps->max_freq_softlimit > rps->min_freq)
2856c349dbc7Sjsg 		rps->max_freq_softlimit--;
2857c349dbc7Sjsg 	spin_unlock_irq(&mchdev_lock);
2858c349dbc7Sjsg 
2859c349dbc7Sjsg 	drm_dev_put(&i915->drm);
2860c349dbc7Sjsg 	return true;
2861c349dbc7Sjsg }
2862c349dbc7Sjsg EXPORT_SYMBOL_GPL(i915_gpu_lower);
2863c349dbc7Sjsg 
2864c349dbc7Sjsg /**
2865c349dbc7Sjsg  * i915_gpu_busy - indicate GPU business to IPS
2866c349dbc7Sjsg  *
2867c349dbc7Sjsg  * Tell the IPS driver whether or not the GPU is busy.
2868c349dbc7Sjsg  */
2869c349dbc7Sjsg bool i915_gpu_busy(void)
2870c349dbc7Sjsg {
2871c349dbc7Sjsg 	struct drm_i915_private *i915;
2872c349dbc7Sjsg 	bool ret;
2873c349dbc7Sjsg 
2874c349dbc7Sjsg 	i915 = mchdev_get();
2875c349dbc7Sjsg 	if (!i915)
2876c349dbc7Sjsg 		return false;
2877c349dbc7Sjsg 
28781bb76ff1Sjsg 	ret = to_gt(i915)->awake;
2879c349dbc7Sjsg 
2880c349dbc7Sjsg 	drm_dev_put(&i915->drm);
2881c349dbc7Sjsg 	return ret;
2882c349dbc7Sjsg }
2883c349dbc7Sjsg EXPORT_SYMBOL_GPL(i915_gpu_busy);
2884c349dbc7Sjsg 
2885c349dbc7Sjsg /**
2886c349dbc7Sjsg  * i915_gpu_turbo_disable - disable graphics turbo
2887c349dbc7Sjsg  *
2888c349dbc7Sjsg  * Disable graphics turbo by resetting the max frequency and setting the
2889c349dbc7Sjsg  * current frequency to the default.
2890c349dbc7Sjsg  */
2891c349dbc7Sjsg bool i915_gpu_turbo_disable(void)
2892c349dbc7Sjsg {
2893c349dbc7Sjsg 	struct drm_i915_private *i915;
2894c349dbc7Sjsg 	struct intel_rps *rps;
2895c349dbc7Sjsg 	bool ret;
2896c349dbc7Sjsg 
2897c349dbc7Sjsg 	i915 = mchdev_get();
2898c349dbc7Sjsg 	if (!i915)
2899c349dbc7Sjsg 		return false;
2900c349dbc7Sjsg 
29011bb76ff1Sjsg 	rps = &to_gt(i915)->rps;
2902c349dbc7Sjsg 
2903c349dbc7Sjsg 	spin_lock_irq(&mchdev_lock);
2904c349dbc7Sjsg 	rps->max_freq_softlimit = rps->min_freq;
29051bb76ff1Sjsg 	ret = !__gen5_rps_set(&to_gt(i915)->rps, rps->min_freq);
2906c349dbc7Sjsg 	spin_unlock_irq(&mchdev_lock);
2907c349dbc7Sjsg 
2908c349dbc7Sjsg 	drm_dev_put(&i915->drm);
2909c349dbc7Sjsg 	return ret;
2910c349dbc7Sjsg }
2911c349dbc7Sjsg EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
2912ad8b1aafSjsg 
2913ad8b1aafSjsg #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
2914ad8b1aafSjsg #include "selftest_rps.c"
29155ca02815Sjsg #include "selftest_slpc.c"
2916ad8b1aafSjsg #endif
2917