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
qdf_ns_to_ktime(uint64_t ns)338 static inline qdf_ktime_t qdf_ns_to_ktime(uint64_t ns)
339 {
340 return __qdf_ns_to_ktime(ns);
341 }
342
qdf_ktime_add(qdf_ktime_t ktime1,qdf_ktime_t ktime2)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
qdf_ktime_get(void)348 static inline qdf_ktime_t qdf_ktime_get(void)
349 {
350 return __qdf_ktime_get();
351 }
352
qdf_ktime_real_get(void)353 static inline qdf_ktime_t qdf_ktime_real_get(void)
354 {
355 return __qdf_ktime_real_get();
356 }
357
qdf_ktime_get_real_ns(void)358 static inline qdf_ktime_t qdf_ktime_get_real_ns(void)
359 {
360 return __qdf_ktime_get_real_ns();
361 }
362
qdf_ktime_get_ns(void)363 static inline uint64_t qdf_ktime_get_ns(void)
364 {
365 return __qdf_ktime_get_ns();
366 }
367
qdf_ktime_compare(qdf_ktime_t ktime1,qdf_ktime_t ktime2)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
qdf_ktime_add_ns(qdf_ktime_t ktime,int64_t ns)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
qdf_ktime_to_ms(qdf_ktime_t ktime)379 static inline int64_t qdf_ktime_to_ms(qdf_ktime_t ktime)
380 {
381 return __qdf_ktime_to_ms(ktime);
382 }
383
qdf_ktime_to_us(qdf_ktime_t ktime)384 static inline int64_t qdf_ktime_to_us(qdf_ktime_t ktime)
385 {
386 return __qdf_time_ktime_to_us(ktime);
387 }
388
qdf_ktime_to_ns(qdf_ktime_t ktime)389 static inline int64_t qdf_ktime_to_ns(qdf_ktime_t ktime)
390 {
391 return __qdf_ktime_to_ns(ktime);
392 }
393
qdf_system_ticks(void)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
qdf_system_ticks_to_msecs(unsigned long clock_ticks)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
qdf_system_msecs_to_ticks(uint32_t msecs)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
qdf_get_system_uptime(void)410 static inline qdf_time_t qdf_get_system_uptime(void)
411 {
412 return __qdf_get_system_uptime();
413 }
414
qdf_get_bootbased_boottime_ns(void)415 static inline uint64_t qdf_get_bootbased_boottime_ns(void)
416 {
417 return __qdf_get_bootbased_boottime_ns();
418 }
419
qdf_get_system_timestamp(void)420 static inline unsigned long qdf_get_system_timestamp(void)
421 {
422 return __qdf_get_system_timestamp();
423 }
424
qdf_udelay(int usecs)425 static inline void qdf_udelay(int usecs)
426 {
427 __qdf_udelay(usecs);
428 }
429
qdf_mdelay(int msecs)430 static inline void qdf_mdelay(int msecs)
431 {
432 __qdf_mdelay(msecs);
433 }
434
qdf_system_time_after(qdf_time_t a,qdf_time_t b)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
qdf_system_time_before(qdf_time_t a,qdf_time_t b)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
qdf_system_time_after_eq(qdf_time_t a,qdf_time_t b)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 */
qdf_sched_clock(void)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
qdf_log_timestamp_to_usecs(uint64_t time)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 */
qdf_get_log_timestamp_lightweight(void)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
qdf_log_timestamp_to_usecs(uint64_t time)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
qdf_get_log_timestamp_lightweight(void)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
qdf_log_timestamp_to_secs(uint64_t time,uint64_t * secs,uint64_t * usecs)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
qdf_usecs_to_log_timestamp(uint64_t usecs)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
qdf_get_log_timestamp(void)546 static inline uint64_t qdf_get_log_timestamp(void)
547 {
548 return __qdf_get_log_timestamp();
549 }
550
qdf_get_log_timestamp_usecs(void)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
qdf_get_monotonic_boottime(void)556 static inline uint64_t qdf_get_monotonic_boottime(void)
557 {
558 return __qdf_get_monotonic_boottime();
559 }
560
qdf_time_ktime_get_real_time(qdf_timespec_t * ts)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
qdf_time_sched_clock(void)566 static inline unsigned long long qdf_time_sched_clock(void)
567 {
568 return __qdf_time_sched_clock();
569 }
570
qdf_usleep_range(unsigned long min,unsigned long max)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