xref: /linux/drivers/gpu/drm/xe/xe_gt_clock.c (revision dd08ebf6c3525a7ea2186e636df064ea47281987)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include "i915_reg.h"
7 #include "gt/intel_gt_regs.h"
8 
9 #include "xe_device.h"
10 #include "xe_gt.h"
11 #include "xe_gt_clock.h"
12 #include "xe_macros.h"
13 #include "xe_mmio.h"
14 
15 static u32 read_reference_ts_freq(struct xe_gt *gt)
16 {
17 	u32 ts_override = xe_mmio_read32(gt, GEN9_TIMESTAMP_OVERRIDE.reg);
18 	u32 base_freq, frac_freq;
19 
20 	base_freq = ((ts_override & GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK) >>
21 		     GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_SHIFT) + 1;
22 	base_freq *= 1000000;
23 
24 	frac_freq = ((ts_override &
25 		      GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK) >>
26 		     GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT);
27 	frac_freq = 1000000 / (frac_freq + 1);
28 
29 	return base_freq + frac_freq;
30 }
31 
32 static u32 get_crystal_clock_freq(u32 rpm_config_reg)
33 {
34 	const u32 f19_2_mhz = 19200000;
35 	const u32 f24_mhz = 24000000;
36 	const u32 f25_mhz = 25000000;
37 	const u32 f38_4_mhz = 38400000;
38 	u32 crystal_clock =
39 		(rpm_config_reg & GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >>
40 		GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT;
41 
42 	switch (crystal_clock) {
43 	case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ:
44 		return f24_mhz;
45 	case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ:
46 		return f19_2_mhz;
47 	case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ:
48 		return f38_4_mhz;
49 	case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ:
50 		return f25_mhz;
51 	default:
52 		XE_BUG_ON("NOT_POSSIBLE");
53 		return 0;
54 	}
55 }
56 
57 int xe_gt_clock_init(struct xe_gt *gt)
58 {
59 	u32 ctc_reg = xe_mmio_read32(gt, CTC_MODE.reg);
60 	u32 freq = 0;
61 
62 	/* Assuming gen11+ so assert this assumption is correct */
63 	XE_BUG_ON(GRAPHICS_VER(gt_to_xe(gt)) < 11);
64 
65 	if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) {
66 		freq = read_reference_ts_freq(gt);
67 	} else {
68 		u32 c0 = xe_mmio_read32(gt, RPM_CONFIG0.reg);
69 
70 		freq = get_crystal_clock_freq(c0);
71 
72 		/*
73 		 * Now figure out how the command stream's timestamp
74 		 * register increments from this frequency (it might
75 		 * increment only every few clock cycle).
76 		 */
77 		freq >>= 3 - ((c0 & GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >>
78 			      GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT);
79 	}
80 
81 	gt->info.clock_freq = freq;
82 	return 0;
83 }
84