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