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