root/kernel/time/timecounter.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. timecounter_init
  2. timecounter_read_delta
  3. timecounter_read
  4. cc_cyc2ns_backwards
  5. timecounter_cyc2time

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Based on clocksource code. See commit 74d23cc704d1
   4  */
   5 #include <linux/export.h>
   6 #include <linux/timecounter.h>
   7 
   8 void timecounter_init(struct timecounter *tc,
   9                       const struct cyclecounter *cc,
  10                       u64 start_tstamp)
  11 {
  12         tc->cc = cc;
  13         tc->cycle_last = cc->read(cc);
  14         tc->nsec = start_tstamp;
  15         tc->mask = (1ULL << cc->shift) - 1;
  16         tc->frac = 0;
  17 }
  18 EXPORT_SYMBOL_GPL(timecounter_init);
  19 
  20 /**
  21  * timecounter_read_delta - get nanoseconds since last call of this function
  22  * @tc:         Pointer to time counter
  23  *
  24  * When the underlying cycle counter runs over, this will be handled
  25  * correctly as long as it does not run over more than once between
  26  * calls.
  27  *
  28  * The first call to this function for a new time counter initializes
  29  * the time tracking and returns an undefined result.
  30  */
  31 static u64 timecounter_read_delta(struct timecounter *tc)
  32 {
  33         u64 cycle_now, cycle_delta;
  34         u64 ns_offset;
  35 
  36         /* read cycle counter: */
  37         cycle_now = tc->cc->read(tc->cc);
  38 
  39         /* calculate the delta since the last timecounter_read_delta(): */
  40         cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
  41 
  42         /* convert to nanoseconds: */
  43         ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta,
  44                                         tc->mask, &tc->frac);
  45 
  46         /* update time stamp of timecounter_read_delta() call: */
  47         tc->cycle_last = cycle_now;
  48 
  49         return ns_offset;
  50 }
  51 
  52 u64 timecounter_read(struct timecounter *tc)
  53 {
  54         u64 nsec;
  55 
  56         /* increment time by nanoseconds since last call */
  57         nsec = timecounter_read_delta(tc);
  58         nsec += tc->nsec;
  59         tc->nsec = nsec;
  60 
  61         return nsec;
  62 }
  63 EXPORT_SYMBOL_GPL(timecounter_read);
  64 
  65 /*
  66  * This is like cyclecounter_cyc2ns(), but it is used for computing a
  67  * time previous to the time stored in the cycle counter.
  68  */
  69 static u64 cc_cyc2ns_backwards(const struct cyclecounter *cc,
  70                                u64 cycles, u64 mask, u64 frac)
  71 {
  72         u64 ns = (u64) cycles;
  73 
  74         ns = ((ns * cc->mult) - frac) >> cc->shift;
  75 
  76         return ns;
  77 }
  78 
  79 u64 timecounter_cyc2time(struct timecounter *tc,
  80                          u64 cycle_tstamp)
  81 {
  82         u64 delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
  83         u64 nsec = tc->nsec, frac = tc->frac;
  84 
  85         /*
  86          * Instead of always treating cycle_tstamp as more recent
  87          * than tc->cycle_last, detect when it is too far in the
  88          * future and treat it as old time stamp instead.
  89          */
  90         if (delta > tc->cc->mask / 2) {
  91                 delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
  92                 nsec -= cc_cyc2ns_backwards(tc->cc, delta, tc->mask, frac);
  93         } else {
  94                 nsec += cyclecounter_cyc2ns(tc->cc, delta, tc->mask, &frac);
  95         }
  96 
  97         return nsec;
  98 }
  99 EXPORT_SYMBOL_GPL(timecounter_cyc2time);

/* [<][>][^][v][top][bottom][index][help] */