xref: /freebsd-src/sys/dev/qat/qat_common/adf_clock.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
1*78ee8d1cSJulian Grajkowski /* SPDX-License-Identifier: BSD-3-Clause */
2*78ee8d1cSJulian Grajkowski /* Copyright(c) 2007-2022 Intel Corporation */
3*78ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
4*78ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
5*78ee8d1cSJulian Grajkowski 
6*78ee8d1cSJulian Grajkowski #include <linux/delay.h>
7*78ee8d1cSJulian Grajkowski 
8*78ee8d1cSJulian Grajkowski #define MEASURE_CLOCK_RETRIES 10
9*78ee8d1cSJulian Grajkowski #define MEASURE_CLOCK_DELTA_THRESHOLD 100
10*78ee8d1cSJulian Grajkowski #define MEASURE_CLOCK_DELAY 10000
11*78ee8d1cSJulian Grajkowski #define ME_CLK_DIVIDER 16
12*78ee8d1cSJulian Grajkowski 
13*78ee8d1cSJulian Grajkowski #define CLK_DBGFS_FILE "frequency"
14*78ee8d1cSJulian Grajkowski #define HB_SYSCTL_ERR(RC)                                                      \
15*78ee8d1cSJulian Grajkowski 	do {                                                                   \
16*78ee8d1cSJulian Grajkowski 		if (!RC) {                                                     \
17*78ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),                      \
18*78ee8d1cSJulian Grajkowski 				      "Memory allocation failed in \
19*78ee8d1cSJulian Grajkowski 				adf_heartbeat_dbg_add\n");                     \
20*78ee8d1cSJulian Grajkowski 			return ENOMEM;                                         \
21*78ee8d1cSJulian Grajkowski 		}                                                              \
22*78ee8d1cSJulian Grajkowski 	} while (0)
23*78ee8d1cSJulian Grajkowski 
24*78ee8d1cSJulian Grajkowski int
adf_clock_debugfs_add(struct adf_accel_dev * accel_dev)25*78ee8d1cSJulian Grajkowski adf_clock_debugfs_add(struct adf_accel_dev *accel_dev)
26*78ee8d1cSJulian Grajkowski {
27*78ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
28*78ee8d1cSJulian Grajkowski 
29*78ee8d1cSJulian Grajkowski 	struct sysctl_ctx_list *qat_sysctl_ctx;
30*78ee8d1cSJulian Grajkowski 	struct sysctl_oid *qat_sysctl_tree;
31*78ee8d1cSJulian Grajkowski 	struct sysctl_oid *rc = 0;
32*78ee8d1cSJulian Grajkowski 
33*78ee8d1cSJulian Grajkowski 	qat_sysctl_ctx =
34*78ee8d1cSJulian Grajkowski 	    device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev);
35*78ee8d1cSJulian Grajkowski 	qat_sysctl_tree =
36*78ee8d1cSJulian Grajkowski 	    device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev);
37*78ee8d1cSJulian Grajkowski 
38*78ee8d1cSJulian Grajkowski 	rc = SYSCTL_ADD_UINT(qat_sysctl_ctx,
39*78ee8d1cSJulian Grajkowski 			     SYSCTL_CHILDREN(qat_sysctl_tree),
40*78ee8d1cSJulian Grajkowski 			     OID_AUTO,
41*78ee8d1cSJulian Grajkowski 			     CLK_DBGFS_FILE,
42*78ee8d1cSJulian Grajkowski 			     CTLFLAG_RD,
43*78ee8d1cSJulian Grajkowski 			     &hw_data->clock_frequency,
44*78ee8d1cSJulian Grajkowski 			     0,
45*78ee8d1cSJulian Grajkowski 			     "clock frequency");
46*78ee8d1cSJulian Grajkowski 	HB_SYSCTL_ERR(rc);
47*78ee8d1cSJulian Grajkowski 	return 0;
48*78ee8d1cSJulian Grajkowski }
49*78ee8d1cSJulian Grajkowski 
50*78ee8d1cSJulian Grajkowski /**
51*78ee8d1cSJulian Grajkowski  * adf_dev_measure_clock() -- Measure the CPM clock frequency
52*78ee8d1cSJulian Grajkowski  * @accel_dev: Pointer to acceleration device.
53*78ee8d1cSJulian Grajkowski  * @frequency: Pointer to returned frequency in Hz.
54*78ee8d1cSJulian Grajkowski  *
55*78ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
56*78ee8d1cSJulian Grajkowski  */
57*78ee8d1cSJulian Grajkowski static int
measure_clock(struct adf_accel_dev * accel_dev,u32 * frequency)58*78ee8d1cSJulian Grajkowski measure_clock(struct adf_accel_dev *accel_dev, u32 *frequency)
59*78ee8d1cSJulian Grajkowski {
60*78ee8d1cSJulian Grajkowski 	struct timespec ts1;
61*78ee8d1cSJulian Grajkowski 	struct timespec ts2;
62*78ee8d1cSJulian Grajkowski 	struct timespec ts3;
63*78ee8d1cSJulian Grajkowski 	struct timespec ts4;
64*78ee8d1cSJulian Grajkowski 	struct timespec delta;
65*78ee8d1cSJulian Grajkowski 	u64 delta_us = 0;
66*78ee8d1cSJulian Grajkowski 	u64 timestamp1 = 0;
67*78ee8d1cSJulian Grajkowski 	u64 timestamp2 = 0;
68*78ee8d1cSJulian Grajkowski 	u64 temp = 0;
69*78ee8d1cSJulian Grajkowski 	int tries = 0;
70*78ee8d1cSJulian Grajkowski 
71*78ee8d1cSJulian Grajkowski 	if (!accel_dev || !frequency)
72*78ee8d1cSJulian Grajkowski 		return EIO;
73*78ee8d1cSJulian Grajkowski 	do {
74*78ee8d1cSJulian Grajkowski 		nanotime(&ts1);
75*78ee8d1cSJulian Grajkowski 		if (adf_get_fw_timestamp(accel_dev, &timestamp1)) {
76*78ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
77*78ee8d1cSJulian Grajkowski 				      "Failed to get fw timestamp\n");
78*78ee8d1cSJulian Grajkowski 			return EIO;
79*78ee8d1cSJulian Grajkowski 		}
80*78ee8d1cSJulian Grajkowski 		nanotime(&ts2);
81*78ee8d1cSJulian Grajkowski 
82*78ee8d1cSJulian Grajkowski 		delta = timespec_sub(ts2, ts1);
83*78ee8d1cSJulian Grajkowski 		temp = delta.tv_nsec;
84*78ee8d1cSJulian Grajkowski 		do_div(temp, NSEC_PER_USEC);
85*78ee8d1cSJulian Grajkowski 
86*78ee8d1cSJulian Grajkowski 		delta_us = delta.tv_sec * USEC_PER_SEC + temp;
87*78ee8d1cSJulian Grajkowski 	} while (delta_us > MEASURE_CLOCK_DELTA_THRESHOLD &&
88*78ee8d1cSJulian Grajkowski 		 ++tries < MEASURE_CLOCK_RETRIES);
89*78ee8d1cSJulian Grajkowski 
90*78ee8d1cSJulian Grajkowski 	if (tries >= MEASURE_CLOCK_RETRIES) {
91*78ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
92*78ee8d1cSJulian Grajkowski 			      "Excessive clock measure delay\n");
93*78ee8d1cSJulian Grajkowski 		return EIO;
94*78ee8d1cSJulian Grajkowski 	}
95*78ee8d1cSJulian Grajkowski 
96*78ee8d1cSJulian Grajkowski 	usleep_range(MEASURE_CLOCK_DELAY, MEASURE_CLOCK_DELAY * 2);
97*78ee8d1cSJulian Grajkowski 	tries = 0;
98*78ee8d1cSJulian Grajkowski 	do {
99*78ee8d1cSJulian Grajkowski 		nanotime(&ts3);
100*78ee8d1cSJulian Grajkowski 		if (adf_get_fw_timestamp(accel_dev, &timestamp2)) {
101*78ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
102*78ee8d1cSJulian Grajkowski 				      "Failed to get fw timestamp\n");
103*78ee8d1cSJulian Grajkowski 			return EIO;
104*78ee8d1cSJulian Grajkowski 		}
105*78ee8d1cSJulian Grajkowski 		nanotime(&ts4);
106*78ee8d1cSJulian Grajkowski 
107*78ee8d1cSJulian Grajkowski 		delta = timespec_sub(ts4, ts3);
108*78ee8d1cSJulian Grajkowski 		temp = delta.tv_nsec;
109*78ee8d1cSJulian Grajkowski 		do_div(temp, NSEC_PER_USEC);
110*78ee8d1cSJulian Grajkowski 
111*78ee8d1cSJulian Grajkowski 		delta_us = delta.tv_sec * USEC_PER_SEC + temp;
112*78ee8d1cSJulian Grajkowski 	} while (delta_us > MEASURE_CLOCK_DELTA_THRESHOLD &&
113*78ee8d1cSJulian Grajkowski 		 ++tries < MEASURE_CLOCK_RETRIES);
114*78ee8d1cSJulian Grajkowski 
115*78ee8d1cSJulian Grajkowski 	if (tries >= MEASURE_CLOCK_RETRIES) {
116*78ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
117*78ee8d1cSJulian Grajkowski 			      "Excessive clock measure delay\n");
118*78ee8d1cSJulian Grajkowski 		return EIO;
119*78ee8d1cSJulian Grajkowski 	}
120*78ee8d1cSJulian Grajkowski 
121*78ee8d1cSJulian Grajkowski 	delta = timespec_sub(ts3, ts1);
122*78ee8d1cSJulian Grajkowski 	temp =
123*78ee8d1cSJulian Grajkowski 	    delta.tv_sec * NSEC_PER_SEC + delta.tv_nsec + (NSEC_PER_USEC / 2);
124*78ee8d1cSJulian Grajkowski 	do_div(temp, NSEC_PER_USEC);
125*78ee8d1cSJulian Grajkowski 	delta_us = temp;
126*78ee8d1cSJulian Grajkowski 	/* Don't pretend that this gives better than 100KHz resolution */
127*78ee8d1cSJulian Grajkowski 	temp = (timestamp2 - timestamp1) * ME_CLK_DIVIDER * 10 + (delta_us / 2);
128*78ee8d1cSJulian Grajkowski 	do_div(temp, delta_us);
129*78ee8d1cSJulian Grajkowski 	*frequency = temp * 100000;
130*78ee8d1cSJulian Grajkowski 
131*78ee8d1cSJulian Grajkowski 	return 0;
132*78ee8d1cSJulian Grajkowski }
133*78ee8d1cSJulian Grajkowski 
134*78ee8d1cSJulian Grajkowski /**
135*78ee8d1cSJulian Grajkowski  * adf_dev_measure_clock() -- Measure the CPM clock frequency
136*78ee8d1cSJulian Grajkowski  * @accel_dev: Pointer to acceleration device.
137*78ee8d1cSJulian Grajkowski  * @frequency: Pointer to returned frequency in Hz.
138*78ee8d1cSJulian Grajkowski  * @min: Minimum expected frequency
139*78ee8d1cSJulian Grajkowski  * @max: Maximum expected frequency
140*78ee8d1cSJulian Grajkowski  *
141*78ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
142*78ee8d1cSJulian Grajkowski  */
143*78ee8d1cSJulian Grajkowski int
adf_dev_measure_clock(struct adf_accel_dev * accel_dev,u32 * frequency,u32 min,u32 max)144*78ee8d1cSJulian Grajkowski adf_dev_measure_clock(struct adf_accel_dev *accel_dev,
145*78ee8d1cSJulian Grajkowski 		      u32 *frequency,
146*78ee8d1cSJulian Grajkowski 		      u32 min,
147*78ee8d1cSJulian Grajkowski 		      u32 max)
148*78ee8d1cSJulian Grajkowski {
149*78ee8d1cSJulian Grajkowski 	int ret;
150*78ee8d1cSJulian Grajkowski 	u32 freq;
151*78ee8d1cSJulian Grajkowski 
152*78ee8d1cSJulian Grajkowski 	ret = measure_clock(accel_dev, &freq);
153*78ee8d1cSJulian Grajkowski 	if (ret)
154*78ee8d1cSJulian Grajkowski 		return ret;
155*78ee8d1cSJulian Grajkowski 
156*78ee8d1cSJulian Grajkowski 	if (freq < min) {
157*78ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
158*78ee8d1cSJulian Grajkowski 			      "Slow clock %d MHz measured, assuming %d\n",
159*78ee8d1cSJulian Grajkowski 			      freq,
160*78ee8d1cSJulian Grajkowski 			      min);
161*78ee8d1cSJulian Grajkowski 		freq = min;
162*78ee8d1cSJulian Grajkowski 	} else if (freq > max) {
163*78ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
164*78ee8d1cSJulian Grajkowski 			      "Fast clock %d MHz measured, assuming %d\n",
165*78ee8d1cSJulian Grajkowski 			      freq,
166*78ee8d1cSJulian Grajkowski 			      max);
167*78ee8d1cSJulian Grajkowski 		freq = max;
168*78ee8d1cSJulian Grajkowski 	}
169*78ee8d1cSJulian Grajkowski 	*frequency = freq;
170*78ee8d1cSJulian Grajkowski 	return 0;
171*78ee8d1cSJulian Grajkowski }
172*78ee8d1cSJulian Grajkowski 
173*78ee8d1cSJulian Grajkowski static inline u64
timespec_to_ms(const struct timespec * ts)174*78ee8d1cSJulian Grajkowski timespec_to_ms(const struct timespec *ts)
175*78ee8d1cSJulian Grajkowski {
176*78ee8d1cSJulian Grajkowski 	return (uint64_t)(ts->tv_sec * (1000)) + (ts->tv_nsec / NSEC_PER_MSEC);
177*78ee8d1cSJulian Grajkowski }
178*78ee8d1cSJulian Grajkowski 
179*78ee8d1cSJulian Grajkowski u64
adf_clock_get_current_time(void)180*78ee8d1cSJulian Grajkowski adf_clock_get_current_time(void)
181*78ee8d1cSJulian Grajkowski {
182*78ee8d1cSJulian Grajkowski 	struct timespec ts;
183*78ee8d1cSJulian Grajkowski 
184*78ee8d1cSJulian Grajkowski 	getnanotime(&ts);
185*78ee8d1cSJulian Grajkowski 	return timespec_to_ms(&ts);
186*78ee8d1cSJulian Grajkowski }
187