blob: e950c81eeeec5d0a4ec8155db6a0110a17b5cfb0 [file] [log] [blame]
Aaron Durbina4217912013-04-29 22:31:51 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google, Inc.
5 *
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.
9 *
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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19#ifndef TIMER_H
20#define TIMER_H
21
22#define USECS_PER_SEC 1000000
23#define MSECS_PER_SEC 1000
24#define USECS_PER_MSEC (USECS_PER_SEC / MSECS_PER_SEC)
25
26/* The time structures are defined to be a representation of the time since
27 * coreboot started executing one of its stages. The reason for using structures
28 * is to allow for changes in the future. The structures' details are exposed
29 * so that the compiler can allocate space on the stack and use in other
30 * structures. In other words, accessing any field within this structure
31 * outside of the core timer code is not supported. */
32
33struct mono_time {
34 long microseconds;
35};
36
37struct rela_time {
38 long microseconds;
39};
40
Aaron Durbin340ca912013-04-30 09:58:12 -050041/* A timeout_callback structure is used for the book keeping for scheduling
42 * work in the future. When a callback is called the structure can be
43 * re-used for scheduling as it is not being tracked by the core timer
44 * library any more. */
45struct timeout_callback {
46 void *priv;
47 void (*callback)(struct timeout_callback *tocb);
48 /* Not for public use. The timer library uses the fields below. */
49 struct mono_time expiration;
50};
51
Aaron Durbina4217912013-04-29 22:31:51 -050052/* Obtain the current monotonic time. The assumption is that the time counts
53 * up from the value 0 with value 0 being the point when the timer was
54 * initialized. Additionally, the timer is assumed to only be valid for the
55 * duration of the boot.
56 *
57 * Note that any implementations of timer_monotonic_get()
58 * need to ensure its timesource does not roll over within 10 secs. The reason
59 * is that the time between calls to timer_monotonic_get() may be on order
60 * of 10 seconds. */
61void timer_monotonic_get(struct mono_time *mt);
62
Aaron Durbin340ca912013-04-30 09:58:12 -050063/* Returns 1 if callbacks still present in the queue. 0 if no timers left. */
64int timers_run(void);
65
66/* Schedule a callback to be ran microseconds from time of invocation.
67 * 0 returned on success, < 0 on error. */
68int timer_sched_callback(struct timeout_callback *tocb, unsigned long us);
69
Aaron Durbina4217912013-04-29 22:31:51 -050070/* Add microseconds to an absoute time. */
71static inline void mono_time_add_usecs(struct mono_time *mt, long us)
72{
73 mt->microseconds += us;
74}
75
76/* Add milliseconds to an absoute time. */
77static inline void mono_time_add_msecs(struct mono_time *mt, long ms)
78{
79 mono_time_add_usecs(mt, ms * USECS_PER_MSEC);
80}
81
82static inline void mono_time_add_rela_time(struct mono_time *mt,
83 const struct rela_time *t)
84{
85 mono_time_add_usecs(mt, t->microseconds);
86}
87
88/* Compare two absoluted times: Return -1, 0, or 1 if t1 is <, =, or > t2,
89 * respectively. */
90static inline int mono_time_cmp(const struct mono_time *t1,
91 const struct mono_time *t2)
92{
93 if (t1->microseconds == t2->microseconds)
94 return 0;
95
96 if (t1->microseconds < t2->microseconds)
97 return -1;
98
99 return 1;
100}
101
102static inline int rela_time_cmp(const struct rela_time *t1,
103 const struct rela_time *t2)
104{
105 if (t1->microseconds == t2->microseconds)
106 return 0;
107
108 if (t1->microseconds < t2->microseconds)
109 return -1;
110
111 return 1;
112}
113
114/* Iniitalize a rela_time structure. */
115static inline struct rela_time rela_time_init_usecs(long us)
116{
117 struct rela_time t;
118 t.microseconds = us;
119 return t;
120}
121
122/* Return time difference between t1 and t2. i.e. t2 - t1. */
123static struct rela_time mono_time_diff(const struct mono_time *t1,
124 const struct mono_time *t2)
125{
126 return rela_time_init_usecs(t2->microseconds - t1->microseconds);
127}
128
129/* Return true if t1 after t2 */
130static inline int mono_time_after(const struct mono_time *t1,
131 const struct mono_time *t2)
132{
133 return mono_time_cmp(t1, t2) > 0;
134}
135
136/* Return true if t1 before t2. */
137static inline int mono_time_before(const struct mono_time *t1,
138 const struct mono_time *t2)
139{
140 return mono_time_cmp(t1, t2) < 0;
141}
142
143/* Return the difference between now and t. */
144static inline struct rela_time current_time_from(const struct mono_time *t)
145{
146 struct mono_time now;
147
148 timer_monotonic_get(&now);
149 return mono_time_diff(t, &now);
150
151}
152
153static inline long rela_time_in_microseconds(const struct rela_time *rt)
154{
155 return rt->microseconds;
156}
157
158#endif /* TIMER_H */