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