xref: /wlan-dirver/qca-wifi-host-cmn/qdf/inc/qdf_time.h (revision 8cfe6b10058a04cafb17eed051f2ddf11bee8931)
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: qdf_time
22  * This file abstracts time related functionality.
23  */
24 
25 #ifndef _QDF_OS_TIME_H
26 #define _QDF_OS_TIME_H
27 
28 #include <i_qdf_time.h>
29 
30 typedef __qdf_time_t qdf_time_t;
31 typedef __qdf_ktime_t qdf_ktime_t;
32 typedef __qdf_timespec_t qdf_timespec_t;
33 typedef __qdf_work_struct_t qdf_work_struct_t;
34 
35 #define qdf_time_uint_to_ms(tu) (((tu) * 1024) / 1000)
36 
37 #ifdef ENHANCED_OS_ABSTRACTION
38 /**
39  * qdf_ns_to_ktime - Converts nanoseconds to a qdf_ktime_t object
40  * @ns: time in nanoseconds
41  *
42  * Return: nanoseconds as qdf_ktime_t object
43  */
44 qdf_ktime_t qdf_ns_to_ktime(uint64_t ns);
45 
46 /**
47  * qdf_ktime_add - Adds two qdf_ktime_t objects and returns
48  * a qdf_ktime_t object
49  * @ktime1: time as qdf_ktime_t object
50  * @ktime2: time as qdf_ktime_t object
51  *
52  * Return: sum of both qdf_ktime_t as qdf_ktime_t object
53  */
54 qdf_ktime_t qdf_ktime_add(qdf_ktime_t ktime1, qdf_ktime_t ktime2);
55 
56 /**
57  * qdf_ktime_get - Gets the current time as qdf_ktime_t object
58  *
59  * Return: current time as qdf_ktime_t object
60  */
61 qdf_ktime_t qdf_ktime_get(void);
62 
63 /**
64  * qdf_ktime_real_get - Gets the current wall clock as qdf_ktime_t object
65  *
66  * Return: current wall clock as qdf_ktime_t object
67  */
68 qdf_ktime_t qdf_ktime_real_get(void);
69 
70 /**
71  * qdf_ktime_add_ns - Adds qdf_ktime_t object and nanoseconds value and
72  * returns the qdf_ktime_t object
73  * @ktime: time as qdf_ktime_t object
74  * @ns: time in nanoseconds
75  *
76  * Return: qdf_ktime_t object
77  */
78 qdf_ktime_t qdf_ktime_add_ns(qdf_ktime_t ktime, int64_t ns);
79 
80 /**
81  * qdf_ktime_to_ms - Convert the qdf_ktime_t object into milliseconds
82  * @ktime: time as qdf_ktime_t object
83  *
84  * Return: qdf_ktime_t in milliseconds
85  */
86 int64_t qdf_ktime_to_ms(qdf_ktime_t ktime);
87 
88 /**
89  * qdf_ktime_to_us - Convert the qdf_ktime_t object into microseconds
90  * @ktime: time as qdf_ktime_t object
91  *
92  * Return: qdf_ktime_t in microseconds
93  */
94 int64_t qdf_ktime_to_us(qdf_ktime_t ktime);
95 
96 /**
97  * qdf_ktime_to_ns - Convert the qdf_ktime_t object into nanoseconds
98  * @ktime: time as qdf_ktime_t object
99  *
100  * Return: qdf_ktime_t in nanoseconds
101  */
102 int64_t qdf_ktime_to_ns(qdf_ktime_t ktime);
103 
104 /**
105  * qdf_system_ticks - Count the number of ticks elapsed from the time when
106  * the system booted
107  *
108  * Return: ticks
109  */
110 qdf_time_t qdf_system_ticks(void);
111 
112 #define qdf_system_ticks_per_sec __qdf_system_ticks_per_sec
113 
114 /**
115  * qdf_system_ticks_to_msecs - convert ticks to milliseconds
116  * @clock_ticks: Number of ticks
117  *
118  * Return: unsigned int Time in milliseconds
119  */
120 uint32_t qdf_system_ticks_to_msecs(unsigned long clock_ticks);
121 
122 /**
123  * qdf_system_msecs_to_ticks - convert milliseconds to ticks
124  * @msec: Time in milliseconds
125  *
126  * Return: unsigned long number of ticks
127  */
128 qdf_time_t qdf_system_msecs_to_ticks(uint32_t msecs);
129 
130 /**
131  * qdf_get_system_uptime - Return a monotonically increasing time
132  * This increments once per HZ ticks
133  *
134  * Return: qdf_time_t system up time in ticks
135  */
136 qdf_time_t qdf_get_system_uptime(void);
137 
138 /**
139  * qdf_get_bootbased_boottime_ns() - Get the bootbased time in nanoseconds
140  *
141  * qdf_get_bootbased_boottime_ns() function returns the number of nanoseconds
142  * that have elapsed since the system was booted. It also includes the time when
143  * system was suspended.
144  *
145  * Return:
146  * The time since system booted in nanoseconds
147  */
148 uint64_t qdf_get_bootbased_boottime_ns(void);
149 
150 /**
151  * qdf_get_system_timestamp - Return current timestamp
152  *
153  * Return: unsigned long timestamp in ms.
154  */
155 unsigned long qdf_get_system_timestamp(void);
156 
157 /**
158  * qdf_udelay - delay in microseconds
159  * @usecs: Number of microseconds to delay
160  *
161  * Return: none
162  */
163 void qdf_udelay(int usecs);
164 
165 /**
166  * qdf_mdelay - Delay in milliseconds.
167  * @msec: Number of milliseconds to delay
168  *
169  * Return: none
170  */
171 void qdf_mdelay(int msecs);
172 
173 /**
174  * qdf_system_time_after() - Check if a is later than b
175  * @a: Time stamp value a
176  * @b: Time stamp value b
177  *
178  * Return: true if a < b else false
179  */
180 bool qdf_system_time_after(qdf_time_t a, qdf_time_t b);
181 
182 /**
183  * qdf_system_time_before() - Check if a is before b
184  * @a: Time stamp value a
185  * @b: Time stamp value b
186  *
187  * Return: true if a is before b else false
188  */
189 bool qdf_system_time_before(qdf_time_t a, qdf_time_t b);
190 
191 /**
192  * qdf_system_time_after_eq() - Check if a atleast as recent as b, if not
193  * later
194  * @a: Time stamp value a
195  * @b: Time stamp value b
196  *
197  * Return: true if a >= b else false
198  */
199 bool qdf_system_time_after_eq(qdf_time_t a, qdf_time_t b);
200 
201 /**
202  * enum qdf_timestamp_unit - what unit the qdf timestamp is in
203  * @KERNEL_LOG: boottime time in uS (micro seconds)
204  * @QTIMER: QTIME in (1/19200)S
205  *
206  * This enum is used to distinguish which timer source is used.
207  */
208 enum qdf_timestamp_unit {
209 	KERNEL_LOG,
210 	QTIMER,
211 };
212 
213 #ifdef MSM_PLATFORM
214 #define QDF_LOG_TIMESTAMP_UNIT QTIMER
215 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 192
216 #else
217 #define QDF_LOG_TIMESTAMP_UNIT KERNEL_LOG
218 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 10
219 #endif /* end of MSM_PLATFORM */
220 
221 uint64_t qdf_log_timestamp_to_usecs(uint64_t time);
222 
223 /**
224  * qdf_get_log_timestamp_to_secs() - get time stamp for logging in seconds
225  *
226  * Return: The current logging timestamp normalized to second precision
227  */
228 void qdf_log_timestamp_to_secs(uint64_t time, uint64_t *secs,
229 			       uint64_t *usecs);
230 
231 uint64_t qdf_usecs_to_log_timestamp(uint64_t usecs);
232 
233 /**
234  * qdf_get_log_timestamp - get time stamp for logging
235  * For adrastea this API returns QTIMER tick which is needed to synchronize
236  * host and fw log timestamps
237  * For ROME and other discrete solution this API returns system boot time stamp
238  *
239  * Return:
240  * QTIMER ticks(19.2MHz) for adrastea
241  * System tick for rome and other future discrete solutions
242  */
243 uint64_t qdf_get_log_timestamp(void);
244 
245 /**
246  * qdf_get_log_timestamp_usecs() - get time stamp for logging in microseconds
247  *
248  * Return: The current logging timestamp normalized to microsecond precision
249  */
250 uint64_t qdf_get_log_timestamp_usecs(void);
251 
252 /**
253  * qdf_get_monotonic_boottime - get monotonic kernel boot time
254  * This API is similar to qdf_get_system_boottime but it includes
255  * time spent in suspend.
256  *
257  * Return: Time in microseconds
258  */
259 uint64_t qdf_get_monotonic_boottime(void);
260 
261 /**
262  * qdf_time_ktime_get_real_time() - Get the time of day in qdf_timespec_t
263  * @ts: pointer to the qdf_timespec_t
264  *
265  * Return: None
266  */
267 void qdf_time_ktime_get_real_time(qdf_timespec_t *ts);
268 
269 /**
270  * qdf_time_sched_clock - scheduler clock
271  *
272  * Return: current time in nanosec units.
273  */
274 unsigned long long qdf_time_sched_clock(void);
275 #else
276 /**
277  * qdf_ns_to_ktime - Converts nanoseconds to a qdf_ktime_t object
278  * @ns: time in nanoseconds
279  *
280  * Return: nanoseconds as qdf_ktime_t object
281  */
282 
283 static inline qdf_ktime_t qdf_ns_to_ktime(uint64_t ns)
284 {
285 	return __qdf_ns_to_ktime(ns);
286 }
287 
288 /**
289  * qdf_ktime_add - Adds two qdf_ktime_t objects and returns
290  * a qdf_ktime_t object
291  * @ktime1: time as qdf_ktime_t object
292  * @ktime2: time as qdf_ktime_t object
293  *
294  * Return: sum of both qdf_ktime_t as qdf_ktime_t object
295  */
296 
297 static inline qdf_ktime_t qdf_ktime_add(qdf_ktime_t ktime1, qdf_ktime_t ktime2)
298 {
299 	return __qdf_ktime_add(ktime1, ktime2);
300 }
301 
302 /**
303  * qdf_ktime_get - Gets the current time as qdf_ktime_t object
304  *
305  * Return: current time as qdf_ktime_t object
306  */
307 
308 static inline qdf_ktime_t qdf_ktime_get(void)
309 {
310 	return __qdf_ktime_get();
311 }
312 
313 /**
314  * qdf_ktime_real_get - Gets the current wall clock as qdf_ktime_t object
315  *
316  * Return: current wall clock as qdf_ktime_t object
317  */
318 
319 static inline qdf_ktime_t qdf_ktime_real_get(void)
320 {
321 	return __qdf_ktime_real_get();
322 }
323 
324 /**
325  * qdf_ktime_add_ns - Adds qdf_ktime_t object and nanoseconds value and
326  * returns the qdf_ktime_t object
327  * @ktime: time as qdf_ktime_t object
328  * @ns: time in nanoseconds
329  *
330  * Return: qdf_ktime_t object
331  */
332 
333 static inline qdf_ktime_t qdf_ktime_add_ns(qdf_ktime_t ktime, int64_t ns)
334 {
335 	return __qdf_ktime_add_ns(ktime, ns);
336 }
337 
338 /**
339  * qdf_ktime_to_ms - Convert the qdf_ktime_t object into milliseconds
340  * @ktime: time as qdf_ktime_t object
341  *
342  * Return: qdf_ktime_t in milliseconds
343  */
344 
345 static inline int64_t qdf_ktime_to_ms(qdf_ktime_t ktime)
346 {
347 	return __qdf_ktime_to_ms(ktime);
348 }
349 
350 /**
351  * qdf_ktime_to_us - Convert the qdf_ktime_t object into microseconds
352  * @ktime: time as qdf_ktime_t object
353  *
354  * Return: qdf_ktime_t in microseconds
355  */
356 
357 static inline int64_t qdf_ktime_to_us(qdf_ktime_t ktime)
358 {
359 	return __qdf_time_ktime_to_us(ktime);
360 }
361 
362 /**
363  * qdf_ktime_to_ns - Convert the qdf_ktime_t object into nanoseconds
364  * @ktime: time as qdf_ktime_t object
365  *
366  * Return: qdf_ktime_t in nanoseconds
367  */
368 
369 static inline int64_t qdf_ktime_to_ns(qdf_ktime_t ktime)
370 {
371 	return __qdf_ktime_to_ns(ktime);
372 }
373 
374 /**
375  * qdf_system_ticks - Count the number of ticks elapsed from the time when
376  * the system booted
377  *
378  * Return: ticks
379  */
380 static inline qdf_time_t qdf_system_ticks(void)
381 {
382 	return __qdf_system_ticks();
383 }
384 
385 #define qdf_system_ticks_per_sec __qdf_system_ticks_per_sec
386 
387 /**
388  * qdf_system_ticks_to_msecs - convert ticks to milliseconds
389  * @clock_ticks: Number of ticks
390  *
391  * Return: unsigned int Time in milliseconds
392  */
393 static inline uint32_t qdf_system_ticks_to_msecs(unsigned long clock_ticks)
394 {
395 	return __qdf_system_ticks_to_msecs(clock_ticks);
396 }
397 
398 /**
399  * qdf_system_msecs_to_ticks - convert milliseconds to ticks
400  * @msec: Time in milliseconds
401  *
402  * Return: unsigned long number of ticks
403  */
404 static inline qdf_time_t qdf_system_msecs_to_ticks(uint32_t msecs)
405 {
406 	return __qdf_system_msecs_to_ticks(msecs);
407 }
408 
409 /**
410  * qdf_get_system_uptime - Return a monotonically increasing time
411  * This increments once per HZ ticks
412  *
413  * Return: qdf_time_t system up time in ticks
414  */
415 static inline qdf_time_t qdf_get_system_uptime(void)
416 {
417 	return __qdf_get_system_uptime();
418 }
419 
420 /**
421  * qdf_get_bootbased_boottime_ns() - Get the bootbased time in nanoseconds
422  *
423  * qdf_get_bootbased_boottime_ns() function returns the number of nanoseconds
424  * that have elapsed since the system was booted. It also includes the time when
425  * system was suspended.
426  *
427  * Return:
428  * The time since system booted in nanoseconds
429  */
430 
431 static inline uint64_t qdf_get_bootbased_boottime_ns(void)
432 {
433 	return __qdf_get_bootbased_boottime_ns();
434 }
435 
436 /**
437  * qdf_get_system_timestamp - Return current timestamp
438  *
439  * Return: unsigned long timestamp in ms.
440  */
441 static inline unsigned long qdf_get_system_timestamp(void)
442 {
443 	return __qdf_get_system_timestamp();
444 }
445 
446 /**
447  * qdf_udelay - delay in microseconds
448  * @usecs: Number of microseconds to delay
449  *
450  * Return: none
451  */
452 static inline void qdf_udelay(int usecs)
453 {
454 	__qdf_udelay(usecs);
455 }
456 
457 /**
458  * qdf_mdelay - Delay in milliseconds.
459  * @msec: Number of milliseconds to delay
460  *
461  * Return: none
462  */
463 static inline void qdf_mdelay(int msecs)
464 {
465 	__qdf_mdelay(msecs);
466 }
467 
468 /**
469  * qdf_system_time_after() - Check if a is later than b
470  * @a: Time stamp value a
471  * @b: Time stamp value b
472  *
473  * Return:
474  * true if a < b else false
475  */
476 static inline bool qdf_system_time_after(qdf_time_t a, qdf_time_t b)
477 {
478 	return __qdf_system_time_after(a, b);
479 }
480 
481 /**
482  * qdf_system_time_before() - Check if a is before b
483  * @a: Time stamp value a
484  * @b: Time stamp value b
485  *
486  * Return:
487  * true if a is before b else false
488  */
489 static inline bool qdf_system_time_before(qdf_time_t a, qdf_time_t b)
490 {
491 	return __qdf_system_time_before(a, b);
492 }
493 
494 /**
495  * qdf_system_time_after_eq() - Check if a atleast as recent as b, if not
496  * later
497  * @a: Time stamp value a
498  * @b: Time stamp value b
499  *
500  * Return:
501  * true if a >= b else false
502  */
503 static inline bool qdf_system_time_after_eq(qdf_time_t a, qdf_time_t b)
504 {
505 	return __qdf_system_time_after_eq(a, b);
506 }
507 
508 /**
509  * qdf_sched_clock() - use light weight timer to get timestamp for logging
510  *
511  * Return: timestamp in ns
512  */
513 static inline uint64_t qdf_sched_clock(void)
514 {
515 	return __qdf_sched_clock();
516 }
517 
518 /**
519  * enum qdf_timestamp_unit - what unit the qdf timestamp is in
520  * @KERNEL_LOG: boottime time in uS (micro seconds)
521  * @QTIMER: QTIME in (1/19200)S
522  *
523  * This enum is used to distinguish which timer source is used.
524  */
525 enum qdf_timestamp_unit {
526 	KERNEL_LOG,
527 	QTIMER,
528 };
529 
530 #ifdef MSM_PLATFORM
531 #define QDF_LOG_TIMESTAMP_UNIT QTIMER
532 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 192
533 
534 static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time)
535 {
536 	/*
537 	 * Try to preserve precision by multiplying by 10 first.
538 	 * If that would cause a wrap around, divide first instead.
539 	 */
540 	if (time * 10 < time) {
541 		do_div(time, QDF_LOG_TIMESTAMP_CYCLES_PER_10_US);
542 		return time * 10;
543 	}
544 
545 	time = time * 10;
546 	do_div(time, QDF_LOG_TIMESTAMP_CYCLES_PER_10_US);
547 
548 	return time;
549 }
550 
551 /**
552  * qdf_get_log_timestamp_lightweight - get time stamp for logging
553  * For adrastea this API returns QTIMER tick which is needed to synchronize
554  * host and fw log timestamps
555  * For ROME and other discrete solution this API returns system boot time stamp
556  *
557  * Return:
558  * QTIMER ticks(19.2MHz) for adrastea
559  * System tick for rome and other 3rd party platform solutions
560  */
561 static inline uint64_t qdf_get_log_timestamp_lightweight(void)
562 {
563 	return __qdf_get_log_timestamp();
564 }
565 #else
566 #define QDF_LOG_TIMESTAMP_UNIT KERNEL_LOG
567 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 10
568 
569 static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time)
570 {
571 	/* timestamps are already in micro seconds */
572 	return time;
573 }
574 
575 static inline uint64_t qdf_get_log_timestamp_lightweight(void)
576 {
577 	uint64_t timestamp_us;
578 
579 	/* explicitly change to uint64_t, otherwise it will assign
580 	 * uint32_t to timestamp_us, which lose high 32bits.
581 	 * on 64bit platform, it will only use low 32bits jiffies in
582 	 * jiffies_to_msecs.
583 	 * eg: HZ=250, it will overflow every (0xffff ffff<<2==0x3fff ffff)
584 	 * ticks. it is 1193 hours.
585 	 */
586 	timestamp_us =
587 	(uint64_t)__qdf_system_ticks_to_msecs(qdf_system_ticks()) * 1000;
588 	return timestamp_us;
589 }
590 #endif /* end of MSM_PLATFORM */
591 
592 static inline void qdf_log_timestamp_to_secs(uint64_t time, uint64_t *secs,
593 					     uint64_t *usecs)
594 {
595 	*secs = qdf_log_timestamp_to_usecs(time);
596 	*usecs = do_div(*secs, 1000000ul);
597 }
598 
599 static inline uint64_t qdf_usecs_to_log_timestamp(uint64_t usecs)
600 {
601 	return (usecs * QDF_LOG_TIMESTAMP_CYCLES_PER_10_US) / 10;
602 }
603 
604 /**
605  * qdf_get_log_timestamp - get time stamp for logging
606  * For adrastea this API returns QTIMER tick which is needed to synchronize
607  * host and fw log timestamps
608  * For ROME and other discrete solution this API returns system boot time stamp
609  *
610  * Return:
611  * QTIMER ticks(19.2MHz) for adrastea
612  * System tick for rome and other future discrete solutions
613  */
614 static inline uint64_t qdf_get_log_timestamp(void)
615 {
616 	return __qdf_get_log_timestamp();
617 }
618 
619 /**
620  * qdf_get_log_timestamp_usecs() - get time stamp for logging in microseconds
621  *
622  * Return: The current logging timestamp normalized to microsecond precision
623  */
624 static inline uint64_t qdf_get_log_timestamp_usecs(void)
625 {
626 	return qdf_log_timestamp_to_usecs(qdf_get_log_timestamp());
627 }
628 
629 /**
630  * qdf_get_monotonic_boottime - get monotonic kernel boot time
631  * This API is similar to qdf_get_system_boottime but it includes
632  * time spent in suspend.
633  *
634  * Return: Time in microseconds
635  */
636 static inline uint64_t qdf_get_monotonic_boottime(void)
637 {
638 	return __qdf_get_monotonic_boottime();
639 }
640 
641 static inline void qdf_time_ktime_get_real_time(qdf_timespec_t *ts)
642 {
643 	return __qdf_time_ktime_get_real_time(ts);
644 }
645 
646 static inline unsigned long long qdf_time_sched_clock(void)
647 {
648 	return __qdf_time_sched_clock();
649 }
650 #endif
651 
652 #endif
653