reset: Convert individual boards to `board_reset()`
[coreboot.git] / src / include / timer.h
blob49eae5ec4077f43571fbeee1970872f5f526acda
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2013 Google, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 #ifndef TIMER_H
16 #define TIMER_H
18 #define NSECS_PER_SEC 1000000000
19 #define USECS_PER_SEC 1000000
20 #define MSECS_PER_SEC 1000
21 #define USECS_PER_MSEC (USECS_PER_SEC / MSECS_PER_SEC)
23 /* The time structures are defined to be a representation of the time since
24 * coreboot started executing one of its stages. The reason for using structures
25 * is to allow for changes in the future. The structures' details are exposed
26 * so that the compiler can allocate space on the stack and use in other
27 * structures. In other words, accessing any field within this structure
28 * outside of the core timer code is not supported. */
30 struct mono_time {
31 long microseconds;
34 /* A timeout_callback structure is used for the book keeping for scheduling
35 * work in the future. When a callback is called the structure can be
36 * re-used for scheduling as it is not being tracked by the core timer
37 * library any more. */
38 struct timeout_callback {
39 void *priv;
40 void (*callback)(struct timeout_callback *tocb);
41 /* Not for public use. The timer library uses the fields below. */
42 struct mono_time expiration;
45 /* Obtain the current monotonic time. The assumption is that the time counts
46 * up from the value 0 with value 0 being the point when the timer was
47 * initialized. Additionally, the timer is assumed to only be valid for the
48 * duration of the boot.
50 * Note that any implementations of timer_monotonic_get()
51 * need to ensure its timesource does not roll over within 10 secs. The reason
52 * is that the time between calls to timer_monotonic_get() may be on order
53 * of 10 seconds. */
54 void timer_monotonic_get(struct mono_time *mt);
56 /* Returns 1 if callbacks still present in the queue. 0 if no timers left. */
57 int timers_run(void);
59 /* Schedule a callback to be ran microseconds from time of invocation.
60 * 0 returned on success, < 0 on error. */
61 int timer_sched_callback(struct timeout_callback *tocb, unsigned long us);
63 /* Set an absolute time to a number of microseconds. */
64 static inline void mono_time_set_usecs(struct mono_time *mt, long us)
66 mt->microseconds = us;
69 /* Set an absolute time to a number of milliseconds. */
70 static inline void mono_time_set_msecs(struct mono_time *mt, long ms)
72 mt->microseconds = ms * USECS_PER_MSEC;
75 /* Add microseconds to an absolute time. */
76 static inline void mono_time_add_usecs(struct mono_time *mt, long us)
78 mt->microseconds += us;
81 /* Add milliseconds to an absolute time. */
82 static inline void mono_time_add_msecs(struct mono_time *mt, long ms)
84 mono_time_add_usecs(mt, ms * USECS_PER_MSEC);
87 /* Compare two absolute times: Return -1, 0, or 1 if t1 is <, =, or > t2,
88 * respectively. */
89 static inline int mono_time_cmp(const struct mono_time *t1,
90 const struct mono_time *t2)
92 if (t1->microseconds == t2->microseconds)
93 return 0;
95 if (t1->microseconds < t2->microseconds)
96 return -1;
98 return 1;
101 /* Return true if t1 after t2 */
102 static inline int mono_time_after(const struct mono_time *t1,
103 const struct mono_time *t2)
105 return mono_time_cmp(t1, t2) > 0;
108 /* Return true if t1 before t2. */
109 static inline int mono_time_before(const struct mono_time *t1,
110 const struct mono_time *t2)
112 return mono_time_cmp(t1, t2) < 0;
115 /* Return time difference between t1 and t2. i.e. t2 - t1. */
116 static inline long mono_time_diff_microseconds(const struct mono_time *t1,
117 const struct mono_time *t2)
119 return t2->microseconds - t1->microseconds;
122 struct stopwatch {
123 struct mono_time start;
124 struct mono_time current;
125 struct mono_time expires;
128 static inline void stopwatch_init(struct stopwatch *sw)
130 if (IS_ENABLED(CONFIG_HAVE_MONOTONIC_TIMER))
131 timer_monotonic_get(&sw->start);
132 else
133 sw->start.microseconds = 0;
135 sw->current = sw->expires = sw->start;
138 static inline void stopwatch_init_usecs_expire(struct stopwatch *sw, long us)
140 stopwatch_init(sw);
141 mono_time_add_usecs(&sw->expires, us);
144 static inline void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
146 stopwatch_init_usecs_expire(sw, USECS_PER_MSEC * ms);
150 * Tick the stopwatch to collect the current time.
152 static inline void stopwatch_tick(struct stopwatch *sw)
154 if (IS_ENABLED(CONFIG_HAVE_MONOTONIC_TIMER))
155 timer_monotonic_get(&sw->current);
156 else
157 sw->current.microseconds = 0;
161 * Tick and check the stopwatch for expiration. Returns non-zero on exipration.
163 static inline int stopwatch_expired(struct stopwatch *sw)
165 stopwatch_tick(sw);
166 return !mono_time_before(&sw->current, &sw->expires);
170 * Tick and check the stopwatch as long as it has not expired.
172 static inline void stopwatch_wait_until_expired(struct stopwatch *sw)
174 while (!stopwatch_expired(sw))
179 * Return number of microseconds since starting the stopwatch.
181 static inline long stopwatch_duration_usecs(struct stopwatch *sw)
184 * If the stopwatch hasn't been ticked (current == start) tick
185 * the stopwatch to gather the accumulated time.
187 if (!mono_time_cmp(&sw->start, &sw->current))
188 stopwatch_tick(sw);
190 return mono_time_diff_microseconds(&sw->start, &sw->current);
193 static inline long stopwatch_duration_msecs(struct stopwatch *sw)
195 return stopwatch_duration_usecs(sw) / USECS_PER_MSEC;
198 #endif /* TIMER_H */