timecounter.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. * linux/kernel/time/timecounter.c
  3. *
  4. * based on code that migrated away from
  5. * linux/kernel/time/clocksource.c
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. */
  17. #include <linux/export.h>
  18. #include <linux/timecounter.h>
  19. void timecounter_init(struct timecounter *tc,
  20. const struct cyclecounter *cc,
  21. u64 start_tstamp)
  22. {
  23. tc->cc = cc;
  24. tc->cycle_last = cc->read(cc);
  25. tc->nsec = start_tstamp;
  26. tc->mask = (1ULL << cc->shift) - 1;
  27. tc->frac = 0;
  28. }
  29. EXPORT_SYMBOL_GPL(timecounter_init);
  30. /**
  31. * timecounter_read_delta - get nanoseconds since last call of this function
  32. * @tc: Pointer to time counter
  33. *
  34. * When the underlying cycle counter runs over, this will be handled
  35. * correctly as long as it does not run over more than once between
  36. * calls.
  37. *
  38. * The first call to this function for a new time counter initializes
  39. * the time tracking and returns an undefined result.
  40. */
  41. static u64 timecounter_read_delta(struct timecounter *tc)
  42. {
  43. u64 cycle_now, cycle_delta;
  44. u64 ns_offset;
  45. /* read cycle counter: */
  46. cycle_now = tc->cc->read(tc->cc);
  47. /* calculate the delta since the last timecounter_read_delta(): */
  48. cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
  49. /* convert to nanoseconds: */
  50. ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta,
  51. tc->mask, &tc->frac);
  52. /* update time stamp of timecounter_read_delta() call: */
  53. tc->cycle_last = cycle_now;
  54. return ns_offset;
  55. }
  56. u64 timecounter_read(struct timecounter *tc)
  57. {
  58. u64 nsec;
  59. /* increment time by nanoseconds since last call */
  60. nsec = timecounter_read_delta(tc);
  61. nsec += tc->nsec;
  62. tc->nsec = nsec;
  63. return nsec;
  64. }
  65. EXPORT_SYMBOL_GPL(timecounter_read);
  66. /*
  67. * This is like cyclecounter_cyc2ns(), but it is used for computing a
  68. * time previous to the time stored in the cycle counter.
  69. */
  70. static u64 cc_cyc2ns_backwards(const struct cyclecounter *cc,
  71. u64 cycles, u64 mask, u64 frac)
  72. {
  73. u64 ns = (u64) cycles;
  74. ns = ((ns * cc->mult) - frac) >> cc->shift;
  75. return ns;
  76. }
  77. u64 timecounter_cyc2time(struct timecounter *tc,
  78. u64 cycle_tstamp)
  79. {
  80. u64 delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
  81. u64 nsec = tc->nsec, frac = tc->frac;
  82. /*
  83. * Instead of always treating cycle_tstamp as more recent
  84. * than tc->cycle_last, detect when it is too far in the
  85. * future and treat it as old time stamp instead.
  86. */
  87. if (delta > tc->cc->mask / 2) {
  88. delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
  89. nsec -= cc_cyc2ns_backwards(tc->cc, delta, tc->mask, frac);
  90. } else {
  91. nsec += cyclecounter_cyc2ns(tc->cc, delta, tc->mask, &frac);
  92. }
  93. return nsec;
  94. }
  95. EXPORT_SYMBOL_GPL(timecounter_cyc2time);