xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_time.h (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: i_qdf_time
22  * This file provides OS dependent time API's.
23  */
24 
25 #ifndef _I_QDF_TIME_H
26 #define _I_QDF_TIME_H
27 
28 #include <linux/version.h>
29 #include <linux/jiffies.h>
30 #include <linux/delay.h>
31 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
32 #include <linux/sched/clock.h>
33 #else
34 #include <linux/sched.h>
35 #endif
36 #include <linux/ktime.h>
37 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
38 #include <linux/timekeeping.h>
39 #else
40 #include <linux/hrtimer.h>
41 #endif
42 #ifdef MSM_PLATFORM
43 #include <asm/arch_timer.h>
44 #endif
45 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
46 #include <linux/sched/clock.h>
47 #else
48 #include <linux/sched.h>
49 #endif
50 
51 typedef unsigned long __qdf_time_t;
52 typedef ktime_t  __qdf_ktime_t;
53 
54 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
55 typedef struct timespec64 __qdf_timespec_t;
56 #else
57 typedef struct timeval __qdf_timespec_t;
58 #endif
59 
60 typedef struct work_struct __qdf_work_struct_t;
61 
62 /**
63  * __qdf_ns_to_ktime() - Converts nanoseconds to a ktime object
64  * @ns: time in nanoseconds
65  *
66  * Return: nanoseconds as ktime object
67  */
68 static inline ktime_t __qdf_ns_to_ktime(uint64_t ns)
69 {
70 	return ns_to_ktime(ns);
71 }
72 
73 /**
74  * __qdf_ktime_add() - Adds two ktime objects and returns
75  * a ktime object
76  * @time1: time as ktime object
77  * @time2: time as ktime object
78  *
79  * Return: sum of ktime objects as ktime object
80  */
81 static inline ktime_t __qdf_ktime_add(ktime_t ktime1, ktime_t ktime2)
82 {
83 	return ktime_add(ktime1, ktime2);
84 }
85 
86 /**
87  * __qdf_ktime_get() - Gets the current time as ktime object
88  *
89  * Return: current time as ktime object
90  */
91 static inline ktime_t __qdf_ktime_get(void)
92 {
93 	return ktime_get();
94 }
95 
96 /**
97  * __qdf_ktime_real_get() - Gets the current wall clock as ktime object
98  *
99  * Return: current wall clock as ktime object
100  */
101 static inline ktime_t __qdf_ktime_real_get(void)
102 {
103 	return ktime_get_real();
104 }
105 
106 /**
107  * __qdf_ktime_add_ns() - Adds ktime object and nanoseconds value and
108  * returns the ktime object
109  *
110  * Return: ktime object
111  */
112 static inline ktime_t __qdf_ktime_add_ns(ktime_t ktime, int64_t ns)
113 {
114 	return ktime_add_ns(ktime, ns);
115 }
116 
117 /**
118  * __qdf_ktime_to_ns() - convert ktime to nanoseconds
119  * @ktime: time as ktime object
120  * @ns: time in nanoseconds
121  *
122  * Return: ktime in nanoseconds
123  */
124 static inline int64_t __qdf_ktime_to_ns(ktime_t ktime)
125 {
126 	return ktime_to_ns(ktime);
127 }
128 
129 /**
130  * __qdf_ktime_to_ms() - convert ktime to milliseconds
131  * @ktime: time as ktime object
132  *
133  * Return: ktime in milliseconds
134  */
135 static inline int64_t __qdf_ktime_to_ms(ktime_t ktime)
136 {
137 	return ktime_to_ms(ktime);
138 }
139 
140 
141 /**
142  * __qdf_system_ticks() - get system ticks
143  *
144  * Return: system tick in jiffies
145  */
146 static inline __qdf_time_t __qdf_system_ticks(void)
147 {
148 	return jiffies;
149 }
150 
151 #define __qdf_system_ticks_per_sec HZ
152 
153 /**
154  * __qdf_system_ticks_to_msecs() - convert system ticks into milli seconds
155  * @ticks: System ticks
156  *
157  * Return: system tick converted into milli seconds
158  */
159 static inline uint32_t __qdf_system_ticks_to_msecs(unsigned long ticks)
160 {
161 	return jiffies_to_msecs(ticks);
162 }
163 
164 /**
165  * __qdf_system_msecs_to_ticks() - convert milli seconds into system ticks
166  * @msecs: Milli seconds
167  *
168  * Return: milli seconds converted into system ticks
169  */
170 static inline __qdf_time_t __qdf_system_msecs_to_ticks(uint32_t msecs)
171 {
172 	return msecs_to_jiffies(msecs);
173 }
174 
175 /**
176  * __qdf_get_system_uptime() - get system uptime
177  *
178  * Return: system uptime in jiffies
179  */
180 static inline __qdf_time_t __qdf_get_system_uptime(void)
181 {
182 	return jiffies;
183 }
184 
185 static inline unsigned long __qdf_get_system_timestamp(void)
186 {
187 	return (jiffies / HZ) * 1000 + (jiffies % HZ) * (1000 / HZ);
188 }
189 
190 #ifdef CONFIG_ARM
191 /**
192  * __qdf_udelay() - delay execution for given microseconds
193  * @usecs: Micro seconds to delay
194  *
195  * Return: none
196  */
197 static inline void __qdf_udelay(uint32_t usecs)
198 {
199 	/*
200 	 * This is in support of XScale build.  They have a limit on the udelay
201 	 * value, so we have to make sure we don't approach the limit
202 	 */
203 	uint32_t mticks;
204 	uint32_t leftover;
205 	int i;
206 	/* slice into 1024 usec chunks (simplifies calculation) */
207 	mticks = usecs >> 10;
208 	leftover = usecs - (mticks << 10);
209 	for (i = 0; i < mticks; i++)
210 		udelay(1024);
211 	udelay(leftover);
212 }
213 #else
214 static inline void __qdf_udelay(uint32_t usecs)
215 {
216 	/* Normal Delay functions. Time specified in microseconds */
217 	udelay(usecs);
218 }
219 #endif
220 
221 /**
222  * __qdf_mdelay() - delay execution for given milliseconds
223  * @usecs: Milliseconds to delay
224  *
225  * Return: none
226  */
227 static inline void __qdf_mdelay(uint32_t msecs)
228 {
229 	mdelay(msecs);
230 }
231 
232 /**
233  * __qdf_system_time_after() - Check if a is later than b
234  * @a: Time stamp value a
235  * @b: Time stamp value b
236  *
237  * Return:
238  * true if a < b else false
239  */
240 static inline bool __qdf_system_time_after(__qdf_time_t a, __qdf_time_t b)
241 {
242 	return (long)(b) - (long)(a) < 0;
243 }
244 
245 /**
246  * __qdf_system_time_before() - Check if a is before b
247  * @a: Time stamp value a
248  * @b: Time stamp value b
249  *
250  * Return:
251  * true if a is before b else false
252  */
253 static inline bool __qdf_system_time_before(__qdf_time_t a, __qdf_time_t b)
254 {
255 	return __qdf_system_time_after(b, a);
256 }
257 
258 /**
259  * __qdf_system_time_after_eq() - Check if a atleast as recent as b, if not
260  * later
261  * @a: Time stamp value a
262  * @b: Time stamp value b
263  *
264  * Return:
265  * true if a >= b else false
266  */
267 static inline bool __qdf_system_time_after_eq(__qdf_time_t a, __qdf_time_t b)
268 {
269 	return (long)(a) - (long)(b) >= 0;
270 }
271 
272 /**
273  * qdf_sched_clock() - use light weight timer to get timestamp
274  *
275  * Return: timestamp in ns
276  */
277 static inline uint64_t __qdf_sched_clock(void)
278 {
279 	return sched_clock();
280 }
281 
282 /**
283  * __qdf_get_monotonic_boottime() - get monotonic kernel boot time
284  * This API is similar to qdf_get_system_boottime but it includes
285  * time spent in suspend.
286  *
287  * Return: Time in microseconds
288  */
289 static inline uint64_t __qdf_get_monotonic_boottime(void)
290 {
291 	return (uint64_t)ktime_to_us(ktime_get_boottime());
292 }
293 
294 #if defined (MSM_PLATFORM)
295 
296 /**
297  * __qdf_get_log_timestamp() - get msm timer ticks
298  *
299  * Returns QTIMER(19.2 MHz) clock ticks. To convert it into seconds
300  * divide it by 19200.
301  *
302  * Return: QTIMER(19.2 MHz) clock ticks
303  */
304 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
305 static inline uint64_t __qdf_get_log_timestamp(void)
306 {
307 	return __arch_counter_get_cntvct();
308 }
309 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
310 static inline uint64_t __qdf_get_log_timestamp(void)
311 {
312 	return arch_counter_get_cntvct();
313 }
314 #else
315 static inline uint64_t __qdf_get_log_timestamp(void)
316 {
317 	return arch_counter_get_cntpct();
318 }
319 #endif /* LINUX_VERSION_CODE */
320 #else
321 
322 /**
323  * __qdf_get_log_timestamp - get time stamp for logging
324  *
325  * Return: system tick for non MSM platforms
326  */
327 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
328 static inline uint64_t __qdf_get_log_timestamp(void)
329 {
330 	struct timespec64 ts;
331 
332 	ktime_get_ts64(&ts);
333 
334 	return ((uint64_t)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
335 }
336 #else
337 static inline uint64_t __qdf_get_log_timestamp(void)
338 {
339 	struct timespec ts;
340 
341 	ktime_get_ts(&ts);
342 
343 	return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
344 }
345 #endif
346 #endif
347 
348 /**
349  * __qdf_get_bootbased_boottime_ns() - Get the bootbased time in nanoseconds
350  *
351  * __qdf_get_bootbased_boottime_ns() function returns the number of nanoseconds
352  * that have elapsed since the system was booted. It also includes the time when
353  * system was suspended.
354  *
355  * Return:
356  * The time since system booted in nanoseconds
357  */
358 
359 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
360 static inline uint64_t __qdf_get_bootbased_boottime_ns(void)
361 {
362 	return ktime_get_boottime_ns();
363 }
364 
365 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
366 static inline uint64_t __qdf_get_bootbased_boottime_ns(void)
367 {
368 	return ktime_get_boot_ns();
369 }
370 
371 #else
372 static inline uint64_t __qdf_get_bootbased_boottime_ns(void)
373 {
374 	return ktime_to_ns(ktime_get_boottime());
375 }
376 #endif
377 
378 /**
379  * __qdf_time_ms_to_ktime() - Converts milliseconds to a ktime object
380  * @ms: time in milliseconds
381  *
382  * Return: milliseconds as ktime object
383  */
384 static inline ktime_t __qdf_time_ms_to_ktime(uint64_t ms)
385 {
386 	return ms_to_ktime(ms);
387 }
388 
389 /**
390  * __qdf_time_ktime_real_get() - Gets the current wall clock as ktime object
391  *
392  * Return: current wall clock as ktime object
393  */
394 static inline ktime_t __qdf_time_ktime_real_get(void)
395 {
396 	return ktime_get_real();
397 }
398 
399 /**
400  * __qdf_time_sched_clock() - schedule clock
401  *
402  * Return: returns current time in nanosec units.
403  */
404 static inline unsigned long long __qdf_time_sched_clock(void)
405 {
406 	return sched_clock();
407 }
408 
409 /**
410  * __qdf_time_ktime_sub() - Subtract two ktime objects and returns
411  * a ktime object
412  * @time1: time as ktime object
413  * @time2: time as ktime object
414  *
415  * Return: subtraction of ktime objects as ktime object
416  */
417 static inline ktime_t __qdf_time_ktime_sub(ktime_t ktime1, ktime_t ktime2)
418 {
419 	return ktime_sub(ktime1, ktime2);
420 }
421 
422 /**
423  * __qdf_time_ktime_set() - Set a ktime_t variable from a seconds/nanoseconds
424  * value
425  * @secs: seconds to set
426  * @nsecs: nanoseconds to set
427  *
428  * Return: The ktime_t representation of the value.
429  */
430 static inline ktime_t __qdf_time_ktime_set(const s64 secs,
431 					   const unsigned long nsecs)
432 {
433 	return ktime_set(secs, nsecs);
434 }
435 
436 /**
437  * __qdf_time_ktime_to_us() - Convert the ktime_t object into microseconds
438  * @ktime: time as ktime_t object
439  *
440  * Return: ktime_t in microseconds
441  */
442 static inline int64_t __qdf_time_ktime_to_us(ktime_t ktime)
443 {
444 	return ktime_to_us(ktime);
445 }
446 
447 /**
448  * __qdf_time_ktime_get_real_time() - Get the time of day in qdf_timespec_t
449  * @ts: pointer to the qdf_timespec_t to be set
450  *
451  * Return: none
452  */
453 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
454 static inline void __qdf_time_ktime_get_real_time(__qdf_timespec_t *ts)
455 {
456 	ktime_get_real_ts64(ts);
457 }
458 #else
459 static inline void __qdf_time_ktime_get_real_time(__qdf_timespec_t *ts)
460 {
461 	do_gettimeofday(ts);
462 }
463 #endif
464 
465 #endif
466