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