xref: /wlan-dirver/qca-wifi-host-cmn/qdf/inc/qdf_time.h (revision 54ab05a36f58e470e5b322a774385b90ea47f785)
1 /*
2  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 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_time_ktime_set() - Set a ktime_t variable from a seconds/nanoseconds
106  * value
107  * @secs: seconds to set
108  * @nsecs: nanoseconds to set
109  *
110  * Return: The qdf_ktime_t representation of the value.
111  */
112 qdf_ktime_t qdf_time_ktime_set(const s64 secs, const unsigned long nsecs);
113 
114 /**
115  * qdf_ktime_get_real_ns() - Gets the current time in ns using UTC
116  *
117  * Return: qdf_ktime_t in nano sec
118  */
119 qdf_ktime_t qdf_ktime_get_real_ns(void);
120 
121 /**
122  * qdf_ktime_get_ns() - Gets the current time nano seconds
123  *
124  * Return: qdf_ktime_t in nano sec
125  */
126 qdf_ktime_t qdf_ktime_get_ns(void);
127 
128 /**
129  * qdf_system_ticks - Count the number of ticks elapsed from the time when
130  * the system booted
131  *
132  * Return: ticks
133  */
134 qdf_time_t qdf_system_ticks(void);
135 
136 #define qdf_system_ticks_per_sec __qdf_system_ticks_per_sec
137 
138 /**
139  * qdf_system_ticks_to_msecs() - convert ticks to milliseconds
140  * @clock_ticks: Number of ticks
141  *
142  * Return: unsigned int Time in milliseconds
143  */
144 uint32_t qdf_system_ticks_to_msecs(unsigned long clock_ticks);
145 
146 /**
147  * qdf_system_ticks_to_nsecs() - convert ticks to nanoseconds
148  * @clock_ticks: Number of ticks
149  *
150  * Return: unsigned int Time in nanoseconds
151  */
152 uint32_t qdf_system_ticks_to_nsecs(unsigned long clock_ticks);
153 
154 /**
155  * qdf_system_msecs_to_ticks() - convert milliseconds to ticks
156  * @msecs: Time in milliseconds
157  *
158  * Return: unsigned long number of ticks
159  */
160 qdf_time_t qdf_system_msecs_to_ticks(uint32_t msecs);
161 
162 /**
163  * qdf_get_system_uptime() - Return a monotonically increasing time
164  * This increments once per HZ ticks
165  *
166  * Return: qdf_time_t system up time in ticks
167  */
168 qdf_time_t qdf_get_system_uptime(void);
169 
170 /**
171  * qdf_get_bootbased_boottime_ns() - Get the bootbased time in nanoseconds
172  *
173  * qdf_get_bootbased_boottime_ns() function returns the number of nanoseconds
174  * that have elapsed since the system was booted. It also includes the time when
175  * system was suspended.
176  *
177  * Return:
178  * The time since system booted in nanoseconds
179  */
180 uint64_t qdf_get_bootbased_boottime_ns(void);
181 
182 /**
183  * qdf_get_system_timestamp() - Return current timestamp
184  *
185  * Return: unsigned long timestamp in ms.
186  */
187 unsigned long qdf_get_system_timestamp(void);
188 
189 /**
190  * qdf_udelay() - delay in microseconds
191  * @usecs: Number of microseconds to delay
192  *
193  * Return: none
194  */
195 void qdf_udelay(int usecs);
196 
197 /**
198  * qdf_mdelay() - Delay in milliseconds.
199  * @msecs: Number of milliseconds to delay
200  *
201  * Return: none
202  */
203 void qdf_mdelay(int msecs);
204 
205 /**
206  * qdf_system_time_after() - Check if a is later than b
207  * @a: Time stamp value a
208  * @b: Time stamp value b
209  *
210  * Return: true if a < b else false
211  */
212 bool qdf_system_time_after(qdf_time_t a, qdf_time_t b);
213 
214 /**
215  * qdf_system_time_before() - Check if a is before b
216  * @a: Time stamp value a
217  * @b: Time stamp value b
218  *
219  * Return: true if a is before b else false
220  */
221 bool qdf_system_time_before(qdf_time_t a, qdf_time_t b);
222 
223 /**
224  * qdf_system_time_after_eq() - Check if a atleast as recent as b, if not
225  * later
226  * @a: Time stamp value a
227  * @b: Time stamp value b
228  *
229  * Return: true if a >= b else false
230  */
231 bool qdf_system_time_after_eq(qdf_time_t a, qdf_time_t b);
232 
233 /**
234  * enum qdf_timestamp_unit - what unit the qdf timestamp is in
235  * @KERNEL_LOG: boottime time in uS (micro seconds)
236  * @QTIMER: QTIME in (1/19200)S
237  *
238  * This enum is used to distinguish which timer source is used.
239  */
240 enum qdf_timestamp_unit {
241 	KERNEL_LOG,
242 	QTIMER,
243 };
244 
245 #ifdef MSM_PLATFORM
246 #define QDF_LOG_TIMESTAMP_UNIT QTIMER
247 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 192
248 #else
249 #define QDF_LOG_TIMESTAMP_UNIT KERNEL_LOG
250 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 10
251 #endif /* end of MSM_PLATFORM */
252 
253 uint64_t qdf_log_timestamp_to_usecs(uint64_t time);
254 
255 /**
256  * qdf_log_timestamp_to_secs() - get time stamp for logging in seconds
257  * @time: logging timestamp
258  * @secs: pointer to write seconds
259  * @usecs: pointer to write microseconds
260  *
261  * Return: void. The normalized time is returned in @secs and @usecs
262  */
263 void qdf_log_timestamp_to_secs(uint64_t time, uint64_t *secs,
264 			       uint64_t *usecs);
265 
266 uint64_t qdf_usecs_to_log_timestamp(uint64_t usecs);
267 
268 /**
269  * qdf_get_log_timestamp() - get time stamp for logging
270  * For adrastea this API returns QTIMER tick which is needed to synchronize
271  * host and fw log timestamps
272  * For ROME and other discrete solution this API returns system boot time stamp
273  *
274  * Return:
275  * QTIMER ticks(19.2MHz) for adrastea
276  * System tick for rome and other future discrete solutions
277  */
278 uint64_t qdf_get_log_timestamp(void);
279 
280 /**
281  * qdf_get_log_timestamp_usecs() - get time stamp for logging in microseconds
282  *
283  * Return: The current logging timestamp normalized to microsecond precision
284  */
285 uint64_t qdf_get_log_timestamp_usecs(void);
286 
287 /**
288  * qdf_get_log_timestamp_lightweight() - get time stamp for logging
289  */
290 #define qdf_get_log_timestamp_lightweight() qdf_get_log_timestamp()
291 
292 /**
293  * qdf_get_monotonic_boottime() - get monotonic kernel boot time
294  * This API is similar to qdf_get_system_boottime but it includes
295  * time spent in suspend.
296  *
297  * Return: Time in microseconds
298  */
299 uint64_t qdf_get_monotonic_boottime(void);
300 
301 /**
302  * qdf_time_ktime_get_real_time() - Get the time of day in qdf_timespec_t
303  * @ts: pointer to the qdf_timespec_t
304  *
305  * Return: None
306  */
307 void qdf_time_ktime_get_real_time(qdf_timespec_t *ts);
308 
309 /**
310  * qdf_time_sched_clock() - scheduler clock
311  *
312  * Return: current time in nanosec units.
313  */
314 unsigned long long qdf_time_sched_clock(void);
315 
316 /**
317  * qdf_usleep_range - introduce sleep with min and max time
318  * @min: Minimum time in usecs to sleep
319  * @max: Maximum time in usecs to sleep
320  *
321  * Return: none
322  */
323 void qdf_usleep_range(unsigned long min, unsigned long max);
324 
325 /**
326  *  qdf_ktime_compare - compare two qdf_ktime_t objects
327  *  @ktime1: time as qdf_ktime_t object
328  *  @ktime2: time as qdf_ktime_t object
329  *
330  *  Return:
331  * * ktime1  < ktime2 - return <0
332  * * ktime1 == ktime2 - return 0
333  * * ktime1  > ktime2 - return >0
334  */
335 int qdf_ktime_compare(qdf_ktime_t ktime1, qdf_ktime_t ktime2);
336 
337 #else
338 static inline qdf_ktime_t qdf_ns_to_ktime(uint64_t ns)
339 {
340 	return __qdf_ns_to_ktime(ns);
341 }
342 
343 static inline qdf_ktime_t qdf_ktime_add(qdf_ktime_t ktime1, qdf_ktime_t ktime2)
344 {
345 	return __qdf_ktime_add(ktime1, ktime2);
346 }
347 
348 static inline qdf_ktime_t qdf_ktime_get(void)
349 {
350 	return __qdf_ktime_get();
351 }
352 
353 static inline qdf_ktime_t qdf_ktime_real_get(void)
354 {
355 	return __qdf_ktime_real_get();
356 }
357 
358 static inline qdf_ktime_t qdf_ktime_get_real_ns(void)
359 {
360 	return __qdf_ktime_get_real_ns();
361 }
362 
363 static inline uint64_t qdf_ktime_get_ns(void)
364 {
365 	return __qdf_ktime_get_ns();
366 }
367 
368 static inline qdf_ktime_t qdf_ktime_compare(qdf_ktime_t ktime1,
369 					    qdf_ktime_t ktime2)
370 {
371 	return __qdf_ktime_compare(ktime1, ktime2);
372 }
373 
374 static inline qdf_ktime_t qdf_ktime_add_ns(qdf_ktime_t ktime, int64_t ns)
375 {
376 	return __qdf_ktime_add_ns(ktime, ns);
377 }
378 
379 static inline int64_t qdf_ktime_to_ms(qdf_ktime_t ktime)
380 {
381 	return __qdf_ktime_to_ms(ktime);
382 }
383 
384 static inline int64_t qdf_ktime_to_us(qdf_ktime_t ktime)
385 {
386 	return __qdf_time_ktime_to_us(ktime);
387 }
388 
389 static inline int64_t qdf_ktime_to_ns(qdf_ktime_t ktime)
390 {
391 	return __qdf_ktime_to_ns(ktime);
392 }
393 
394 static inline qdf_time_t qdf_system_ticks(void)
395 {
396 	return __qdf_system_ticks();
397 }
398 
399 #define qdf_system_ticks_per_sec __qdf_system_ticks_per_sec
400 static inline uint32_t qdf_system_ticks_to_msecs(unsigned long clock_ticks)
401 {
402 	return __qdf_system_ticks_to_msecs(clock_ticks);
403 }
404 
405 static inline qdf_time_t qdf_system_msecs_to_ticks(uint32_t msecs)
406 {
407 	return __qdf_system_msecs_to_ticks(msecs);
408 }
409 
410 static inline qdf_time_t qdf_get_system_uptime(void)
411 {
412 	return __qdf_get_system_uptime();
413 }
414 
415 static inline uint64_t qdf_get_bootbased_boottime_ns(void)
416 {
417 	return __qdf_get_bootbased_boottime_ns();
418 }
419 
420 static inline unsigned long qdf_get_system_timestamp(void)
421 {
422 	return __qdf_get_system_timestamp();
423 }
424 
425 static inline void qdf_udelay(int usecs)
426 {
427 	__qdf_udelay(usecs);
428 }
429 
430 static inline void qdf_mdelay(int msecs)
431 {
432 	__qdf_mdelay(msecs);
433 }
434 
435 static inline bool qdf_system_time_after(qdf_time_t a, qdf_time_t b)
436 {
437 	return __qdf_system_time_after(a, b);
438 }
439 
440 static inline bool qdf_system_time_before(qdf_time_t a, qdf_time_t b)
441 {
442 	return __qdf_system_time_before(a, b);
443 }
444 
445 static inline bool qdf_system_time_after_eq(qdf_time_t a, qdf_time_t b)
446 {
447 	return __qdf_system_time_after_eq(a, b);
448 }
449 
450 /**
451  * qdf_sched_clock() - use light weight timer to get timestamp for logging
452  *
453  * Return: timestamp in ns
454  */
455 static inline uint64_t qdf_sched_clock(void)
456 {
457 	return __qdf_sched_clock();
458 }
459 
460 /**
461  * enum qdf_timestamp_unit - what unit the qdf timestamp is in
462  * @KERNEL_LOG: boottime time in uS (micro seconds)
463  * @QTIMER: QTIME in (1/19200)S
464  *
465  * This enum is used to distinguish which timer source is used.
466  */
467 enum qdf_timestamp_unit {
468 	KERNEL_LOG,
469 	QTIMER,
470 };
471 
472 #ifdef MSM_PLATFORM
473 #define QDF_LOG_TIMESTAMP_UNIT QTIMER
474 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 192
475 
476 static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time)
477 {
478 	/*
479 	 * Try to preserve precision by multiplying by 10 first.
480 	 * If that would cause a wrap around, divide first instead.
481 	 */
482 	if (time * 10 < time) {
483 		do_div(time, QDF_LOG_TIMESTAMP_CYCLES_PER_10_US);
484 		return time * 10;
485 	}
486 
487 	time = time * 10;
488 	do_div(time, QDF_LOG_TIMESTAMP_CYCLES_PER_10_US);
489 
490 	return time;
491 }
492 
493 /**
494  * qdf_get_log_timestamp_lightweight() - get time stamp for logging
495  * For adrastea this API returns QTIMER tick which is needed to synchronize
496  * host and fw log timestamps
497  * For ROME and other discrete solution this API returns system boot time stamp
498  *
499  * Return:
500  * QTIMER ticks(19.2MHz) for adrastea
501  * System tick for rome and other 3rd party platform solutions
502  */
503 static inline uint64_t qdf_get_log_timestamp_lightweight(void)
504 {
505 	return __qdf_get_log_timestamp();
506 }
507 #else
508 #define QDF_LOG_TIMESTAMP_UNIT KERNEL_LOG
509 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 10
510 
511 static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time)
512 {
513 	/* timestamps are already in micro seconds */
514 	return time;
515 }
516 
517 static inline uint64_t qdf_get_log_timestamp_lightweight(void)
518 {
519 	uint64_t timestamp_us;
520 
521 	/* explicitly change to uint64_t, otherwise it will assign
522 	 * uint32_t to timestamp_us, which lose high 32bits.
523 	 * on 64bit platform, it will only use low 32bits jiffies in
524 	 * jiffies_to_msecs.
525 	 * eg: HZ=250, it will overflow every (0xffff ffff<<2==0x3fff ffff)
526 	 * ticks. it is 1193 hours.
527 	 */
528 	timestamp_us =
529 	(uint64_t)__qdf_system_ticks_to_msecs(qdf_system_ticks()) * 1000;
530 	return timestamp_us;
531 }
532 #endif /* end of MSM_PLATFORM */
533 
534 static inline void qdf_log_timestamp_to_secs(uint64_t time, uint64_t *secs,
535 					     uint64_t *usecs)
536 {
537 	*secs = qdf_log_timestamp_to_usecs(time);
538 	*usecs = do_div(*secs, 1000000ul);
539 }
540 
541 static inline uint64_t qdf_usecs_to_log_timestamp(uint64_t usecs)
542 {
543 	return (usecs * QDF_LOG_TIMESTAMP_CYCLES_PER_10_US) / 10;
544 }
545 
546 static inline uint64_t qdf_get_log_timestamp(void)
547 {
548 	return __qdf_get_log_timestamp();
549 }
550 
551 static inline uint64_t qdf_get_log_timestamp_usecs(void)
552 {
553 	return qdf_log_timestamp_to_usecs(qdf_get_log_timestamp());
554 }
555 
556 static inline uint64_t qdf_get_monotonic_boottime(void)
557 {
558 	return __qdf_get_monotonic_boottime();
559 }
560 
561 static inline void qdf_time_ktime_get_real_time(qdf_timespec_t *ts)
562 {
563 	return __qdf_time_ktime_get_real_time(ts);
564 }
565 
566 static inline unsigned long long qdf_time_sched_clock(void)
567 {
568 	return __qdf_time_sched_clock();
569 }
570 
571 static inline void qdf_usleep_range(unsigned long min, unsigned long max)
572 {
573 	__qdf_usleep_range(min, max);
574 }
575 #endif
576 #endif
577