1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #ifndef FWK_TIME_H
9 #define FWK_TIME_H
10 
11 #include <fwk_assert.h>
12 #include <fwk_id.h>
13 
14 #include <inttypes.h>
15 #include <stdint.h>
16 
17 struct fwk_arch_counter_driver;
18 
19 /*!
20  * \addtogroup GroupLibFramework
21  * \defgroup GroupTime Time operations.
22  *
23  * \details This component adds support for various time operations, including
24  *      timestamping and duration calculations. It also provides facilities for
25  *      converting between units of time as well as printing them using the
26  *      standard framework printing and logging facilities.
27  *
28  * \{
29  */
30 
31 /*!
32  * \brief Create a nanosecond duration.
33  *
34  * \param[in] N Number of nanoseconds.
35  *
36  * \return A value of type ::fwk_duration_ns_t representing the duration \p N.
37  */
38 #define FWK_NS(N) ((fwk_duration_ns_t)(N))
39 
40 /*!
41  * \brief Create a nanosecond duration from a microsecond value.
42  *
43  * \param[in] N Number of microseconds.
44  *
45  * \return A value of type ::fwk_duration_ns_t representing the duration \p N.
46  */
47 #define FWK_US(N) FWK_NS((N) * UINT64_C(1000))
48 
49 /*!
50  * \brief Create a nanosecond duration from a millisecond value.
51  *
52  * \param[in] N Number of milliseconds.
53  *
54  * \return A value of type ::fwk_duration_ns_t representing the duration \p N.
55  */
56 #define FWK_MS(N) FWK_US((N) * UINT64_C(1000))
57 
58 /*!
59  * \brief Create a nanosecond duration from a second value.
60  *
61  * \param[in] N Number of seconds.
62  *
63  * \return A value of type ::fwk_duration_ns_t representing the duration \p N.
64  */
65 #define FWK_S(N) FWK_MS((N) * UINT64_C(1000))
66 
67 /*!
68  * \brief Create a nanosecond duration from a minute value.
69  *
70  * \param[in] N Number of minutes.
71  *
72  * \return A value of type ::fwk_duration_ns_t representing the duration \p N.
73  */
74 #define FWK_M(N) FWK_S((N) * UINT64_C(60))
75 
76 /*!
77  * \brief Create a nanosecond duration from an hour value.
78  *
79  * \param[in] N Number of hours.
80  *
81  * \return A value of type ::fwk_duration_ns_t representing the duration \p N.
82  */
83 #define FWK_H(N) (FWK_M(N * UINT64_C(60)))
84 
85 /*!
86  * \brief Format specifier for ::fwk_duration_ns_t.
87  */
88 #define FWK_PRDNS PRIu64
89 
90 /*!
91  * \brief Format specifier for ::fwk_duration_us_t.
92  */
93 #define FWK_PRDUS PRIu64
94 
95 /*!
96  * \brief Format specifier for ::fwk_duration_ms_t.
97  */
98 #define FWK_PRDMS PRIu64
99 
100 /*!
101  * \brief Format specifier for ::fwk_duration_s_t.
102  */
103 #define FWK_PRDS PRIu64
104 
105 /*!
106  * \brief Format specifier for ::fwk_duration_m_t.
107  */
108 #define FWK_PRDM PRIu32
109 
110 /*!
111  * \brief Format specifier for ::fwk_duration_h_t.
112  */
113 #define FWK_PRDH PRIu32
114 
115 /*!
116  * \brief A timestamp, representing nanoseconds since boot.
117  */
118 typedef uint64_t fwk_timestamp_t;
119 
120 /*!
121  * \brief A duration of time measured in nanoseconds.
122  */
123 typedef uint64_t fwk_duration_ns_t;
124 
125 /*!
126  * \brief A duration of time measured in microseconds.
127  */
128 typedef uint64_t fwk_duration_us_t;
129 
130 /*!
131  * \brief A duration of time measured in milliseconds.
132  */
133 typedef uint64_t fwk_duration_ms_t;
134 
135 /*!
136  * \brief A duration of time measured in seconds.
137  */
138 typedef uint64_t fwk_duration_s_t;
139 
140 /*!
141  * \brief A duration of time measured in minutes.
142  */
143 typedef uint32_t fwk_duration_m_t;
144 
145 /*!
146  * \brief A duration of time measured in hours.
147  */
148 typedef uint32_t fwk_duration_h_t;
149 
150 /*!
151  * \brief Get a timestamp representing the current time.
152  *
153  * \return Current timestamp.
154  */
155 fwk_timestamp_t fwk_time_current(void);
156 
157 /*!
158  * \brief Convert a timestamp to duration since boot, in nanoseconds.
159  *
160  * \param[in] timestamp Timestamp.
161  *
162  * \return Duration of time since boot, in nanoseconds.
163  */
164 fwk_duration_ns_t fwk_time_stamp_duration(fwk_timestamp_t timestamp);
165 
166 /*!
167  * \brief Get the duration of time between two points.
168  *
169  * \param[in] start Timestamp representing the beginning of the measurement.
170  * \param[in] end Timestamp representing the end of the measurement.
171  *
172  * \return Duration of time between two points, in nanoseconds.
173  */
174 fwk_duration_ns_t fwk_time_duration(fwk_timestamp_t start, fwk_timestamp_t end);
175 
176 /*!
177  * \brief Convert a nanosecond duration to a microsecond duration.
178  *
179  * \param[in] duration Duration in nanoseconds.
180  *
181  * \return Duration in microseconds.
182  */
183 fwk_duration_us_t fwk_time_duration_us(fwk_duration_ns_t duration);
184 
185 /*!
186  * \brief Convert a nanosecond duration to a millisecond duration.
187  *
188  * \param[in] duration Duration in nanoseconds.
189  *
190  * \return Duration in milliseconds.
191  */
192 fwk_duration_ms_t fwk_time_duration_ms(fwk_duration_ns_t duration);
193 
194 /*!
195  * \brief Convert a nanosecond duration to a second duration.
196  *
197  * \param[in] duration Duration in nanoseconds.
198  *
199  * \return Duration in seconds.
200  */
201 fwk_duration_s_t fwk_time_duration_s(fwk_duration_ns_t duration);
202 
203 /*!
204  * \brief Convert a nanosecond duration to a minute duration.
205  *
206  * \param[in] duration Duration in nanoseconds.
207  *
208  * \return Duration in minutes.
209  */
210 fwk_duration_m_t fwk_time_duration_m(fwk_duration_ns_t duration);
211 
212 /*!
213  * \brief Convert a nanosecond duration to an hour duration.
214  *
215  * \param[in] duration Duration in nanoseconds.
216  *
217  * \return Duration in hours.
218  */
219 fwk_duration_h_t fwk_time_duration_h(fwk_duration_ns_t duration);
220 
221 /*!
222  * \brief Time driver.
223  */
224 struct fwk_time_driver {
225     /*!
226      * \brief Read the current timestamp value.
227      *
228      * \param[in] Driver-specific context given by the firmware.
229      *
230      * \return Current timestamp.
231      */
232     fwk_timestamp_t (*timestamp)(const void *ctx);
233 };
234 
235 /*!
236  * \brief Register a framework time driver.
237  *
238  * \details In order to update timestamp details on demand, the framework needs
239  *      to reach out to a particular device. This is done through the time
240  *      driver, which should be configured to read from a particular counter in
241  *      the system.
242  *
243  *      This is a weak function provided by the framework that, by default, does
244  *      not register a driver, and should be overridden by the firmware if you
245  *      wish to provide one.
246  *
247  * \param[out] ctx Context specific to the driver, provided to calls to the
248  *      driver API.
249  *
250  * \return Framework time driver.
251  */
252 struct fwk_time_driver fmw_time_driver(const void **ctx);
253 
254 /*!
255  * \}
256  */
257 
258 #endif /* FWK_TIME_H */
259