xref: /linux/drivers/gpu/drm/xe/xe_gt_clock.c (revision e7aaa5fbf4fc1aa9c348075aab9bf054727f025f)
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 static u32 get_crystal_clock_freq(u32 rpm_config_reg)
20 {
21 	const u32 f19_2_mhz = 19200000;
22 	const u32 f24_mhz = 24000000;
23 	const u32 f25_mhz = 25000000;
24 	const u32 f38_4_mhz = 38400000;
25 	u32 crystal_clock = REG_FIELD_GET(RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK,
26 					  rpm_config_reg);
27 
28 	switch (crystal_clock) {
29 	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ:
30 		return f24_mhz;
31 	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ:
32 		return f19_2_mhz;
33 	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ:
34 		return f38_4_mhz;
35 	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ:
36 		return f25_mhz;
37 	default:
38 		XE_WARN_ON("NOT_POSSIBLE");
39 		return 0;
40 	}
41 }
42 
43 int xe_gt_clock_init(struct xe_gt *gt)
44 {
45 	u32 c0 = xe_mmio_read32(&gt->mmio, RPM_CONFIG0);
46 	u32 freq = 0;
47 
48 	/*
49 	 * CTC_MODE[0] = 1 is definitely not supported for Xe2 and later
50 	 * platforms.  In theory it could be a valid setting for pre-Xe2
51 	 * platforms, but there's no documentation on how to properly handle
52 	 * this case.  Reading TIMESTAMP_OVERRIDE, as the driver attempted in
53 	 * the past has been confirmed as incorrect by the hardware architects.
54 	 *
55 	 * For now just warn if we ever encounter hardware in the wild that
56 	 * has this setting and move on as if it hadn't been set.
57 	 */
58 	if (xe_mmio_read32(&gt->mmio, CTC_MODE) & CTC_SOURCE_DIVIDE_LOGIC)
59 		xe_gt_warn(gt, "CTC_MODE[0] is set; this is unexpected and undocumented\n");
60 
61 	freq = get_crystal_clock_freq(c0);
62 
63 	/*
64 	 * Now figure out how the command stream's timestamp
65 	 * register increments from this frequency (it might
66 	 * increment only every few clock cycle).
67 	 */
68 	freq >>= 3 - REG_FIELD_GET(RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK, c0);
69 
70 	gt->info.reference_clock = freq;
71 	return 0;
72 }
73 
74 static u64 div_u64_roundup(u64 n, u32 d)
75 {
76 	return div_u64(n + d - 1, d);
77 }
78 
79 /**
80  * xe_gt_clock_interval_to_ms - Convert sampled GT clock ticks to msec
81  *
82  * @gt: the &xe_gt
83  * @count: count of GT clock ticks
84  *
85  * Returns: time in msec
86  */
87 u64 xe_gt_clock_interval_to_ms(struct xe_gt *gt, u64 count)
88 {
89 	return div_u64_roundup(count * MSEC_PER_SEC, gt->info.reference_clock);
90 }
91