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