xref: /linux/drivers/gpu/drm/xe/xe_gt_clock.c (revision ca220141fa8ebae09765a242076b2b77338106b0)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include <linux/math64.h>
7 
8 #include "xe_gt_clock.h"
9 
10 #include "regs/xe_gt_regs.h"
11 #include "xe_gt_types.h"
12 #include "xe_gt_printk.h"
13 #include "xe_mmio.h"
14 
15 #define f19_2_mhz	19200000
16 #define f24_mhz		24000000
17 #define f25_mhz		25000000
18 #define f38_4_mhz	38400000
19 #define ts_base_83	83333
20 #define ts_base_52	52083
21 #define ts_base_80	80000
22 
23 static void read_crystal_clock(struct xe_gt *gt, u32 rpm_config_reg, u32 *freq,
24 			       u32 *timestamp_base)
25 {
26 	u32 crystal_clock = REG_FIELD_GET(RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK,
27 					  rpm_config_reg);
28 
29 	switch (crystal_clock) {
30 	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ:
31 		*freq = f24_mhz;
32 		*timestamp_base = ts_base_83;
33 		return;
34 	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ:
35 		*freq = f19_2_mhz;
36 		*timestamp_base = ts_base_52;
37 		return;
38 	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ:
39 		*freq = f38_4_mhz;
40 		*timestamp_base = ts_base_52;
41 		return;
42 	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ:
43 		*freq = f25_mhz;
44 		*timestamp_base = ts_base_80;
45 		return;
46 	default:
47 		xe_gt_warn(gt, "Invalid crystal clock frequency: %u", crystal_clock);
48 		*freq = 0;
49 		*timestamp_base = 0;
50 		return;
51 	}
52 }
53 
54 int xe_gt_clock_init(struct xe_gt *gt)
55 {
56 	u32 freq;
57 	u32 c0;
58 
59 	c0 = xe_mmio_read32(&gt->mmio, RPM_CONFIG0);
60 	read_crystal_clock(gt, c0, &freq, &gt->info.timestamp_base);
61 
62 	/*
63 	 * Now figure out how the command stream's timestamp
64 	 * register increments from this frequency (it might
65 	 * increment only every few clock cycle).
66 	 */
67 	freq >>= 3 - REG_FIELD_GET(RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK, c0);
68 
69 	gt->info.reference_clock = freq;
70 	return 0;
71 }
72 
73 /**
74  * xe_gt_clock_interval_to_ms - Convert sampled GT clock ticks to msec
75  *
76  * @gt: the &xe_gt
77  * @count: count of GT clock ticks
78  *
79  * Returns: time in msec
80  */
81 u64 xe_gt_clock_interval_to_ms(struct xe_gt *gt, u64 count)
82 {
83 	return mul_u64_u32_div(count, MSEC_PER_SEC, gt->info.reference_clock);
84 }
85