1 /* 2 * Arm SCP/MCP Software 3 * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Description: 8 * Timer HAL 9 */ 10 11 #ifndef MOD_TIMER_H 12 #define MOD_TIMER_H 13 14 #include <fwk_id.h> 15 #include <fwk_module_idx.h> 16 17 #include <stdbool.h> 18 #include <stdint.h> 19 20 /*! 21 * \addtogroup GroupModules Modules 22 * \{ 23 */ 24 25 /*! 26 * \defgroup GroupModuleTimer Timer HAL 27 * 28 * \brief Hardware Abstraction Layer for Timers. 29 * 30 * \details Provides functionality for setting timer events, tracking elapsed 31 * time, and synchronously delaying execution. 32 * 33 * \{ 34 */ 35 36 /*! 37 * \brief Timer module API indicies 38 */ 39 enum mod_timer_api_idx { 40 /*! Timer API index */ 41 MOD_TIMER_API_IDX_TIMER, 42 43 /*! Alarm API index */ 44 MOD_TIMER_API_IDX_ALARM, 45 46 /*! Number of APIs */ 47 MOD_TIMER_API_COUNT, 48 }; 49 50 /*! 51 * \brief Timer API ID 52 */ 53 #define MOD_TIMER_API_ID_TIMER FWK_ID_API(FWK_MODULE_IDX_TIMER, \ 54 MOD_TIMER_API_IDX_TIMER) 55 56 /*! 57 * \brief Alarm API ID 58 */ 59 #define MOD_TIMER_API_ID_ALARM FWK_ID_API(FWK_MODULE_IDX_TIMER, \ 60 MOD_TIMER_API_IDX_ALARM) 61 62 /*! 63 * \brief Alarm type. 64 */ 65 enum mod_timer_alarm_type { 66 /*! Alarm that will trigger once */ 67 MOD_TIMER_ALARM_TYPE_ONCE, 68 69 /*! Alarm that will trigger at regular intervals */ 70 MOD_TIMER_ALARM_TYPE_PERIODIC, 71 72 /*! Number of alarm types */ 73 MOD_TIMER_ALARM_TYPE_COUNT, 74 }; 75 76 /*! 77 * \brief Timer device descriptor 78 */ 79 struct mod_timer_dev_config { 80 /*! Element identifier for the device's associated driver */ 81 fwk_id_t id; 82 83 /*! Timer device IRQ number */ 84 unsigned int timer_irq; 85 }; 86 87 /*! 88 * \brief Timer driver interface. 89 */ 90 struct mod_timer_driver_api { 91 /*! Name of the driver. */ 92 const char *name; 93 94 /*! 95 * Enable timer events 96 * It is expected that the driver enables the timer's interrupt 97 * source (i.e. using the timer's registers) within this function. 98 */ 99 int (*enable)(fwk_id_t dev_id); 100 101 /*! 102 * Disable timer events 103 * It is expected that the driver disables the timer's interrupt 104 * source (i.e.using the timer's registers) within this function. 105 */ 106 int (*disable)(fwk_id_t dev_id); 107 108 /*! 109 * Set timer event for a specified timestamp 110 * The timer HAL clears the interrupt via the framework interrupt interface. 111 * So it is expected from the timer driver to set the timer value only. 112 */ 113 int (*set_timer)(fwk_id_t dev_id, uint64_t timestamp); 114 115 /*! Get remaining time until the next pending timer event is due to fire */ 116 int (*get_timer)(fwk_id_t dev_id, uint64_t *timestamp); 117 118 /*! Get current counter value */ 119 int (*get_counter)(fwk_id_t dev_id, uint64_t *value); 120 121 /*! Get counter frequency */ 122 int (*get_frequency)(fwk_id_t dev_id, uint32_t *value); 123 }; 124 125 /*! 126 * \brief Timer HAL interface 127 */ 128 struct mod_timer_api { 129 /*! 130 * \brief Get the frequency of a given timer. 131 * 132 * \details Get the frequency in Hertz (Hz) that a timer is running at. 133 * 134 * \param dev_id Element identifier that identifies the timer device. 135 * \param[out] frequency The timer frequency. 136 * 137 * \retval ::FWK_SUCCESS Operation succeeded. 138 * \retval ::FWK_E_PARAM The frequency pointer was invalid. 139 * \retval One of the other specific error codes described by the framework. 140 */ 141 int (*get_frequency)(fwk_id_t dev_id, uint32_t *frequency); 142 143 /*! 144 * \brief Get a counter timestamp that represents a given time period in 145 * microseconds (µS). 146 * 147 * \note The value of the resulting timestamp is only valid for the given 148 * device, since other timer devices may operate at different rates. 149 * 150 * \param dev_id Element identifier that identifies the timer device. 151 * \param microseconds Period, in microseconds. 152 * \param[out] timestamp The resulting counter timestamp. 153 * 154 * \retval ::FWK_SUCCESS Operation succeeded. 155 * \retval ::FWK_E_PARAM The timestamp pointer was invalid. 156 * \retval One of the other specific error codes described by the framework. 157 */ 158 int (*time_to_timestamp)(fwk_id_t dev_id, 159 uint32_t microseconds, 160 uint64_t *timestamp); 161 162 /*! 163 * \brief Get the current counter value of a given timer. 164 * 165 * \details Directly returns the counter value of the timer at the present 166 * moment. 167 * 168 * \param dev_id Element identifier that identifies the timer device. 169 * \param[out] counter The counter value. 170 * 171 * \retval ::FWK_SUCCESS Operation succeeded. 172 * \retval ::FWK_E_PARAM The counter pointer was invalid. 173 * \retval One of the other specific error codes described by the framework. 174 */ 175 int (*get_counter)(fwk_id_t dev_id, uint64_t *counter); 176 177 /*! 178 * \brief Delay execution by synchronously waiting for a specified amount 179 * of time. 180 * 181 * \details Blocks the calling thread for the specified amount of time. 182 * 183 * \param dev_id Element identifier that identifies the timer device. 184 * \param microseconds The amount of time, given in microseconds, to delay. 185 * 186 * \retval ::FWK_SUCCESS Operation succeeded. 187 * \retval One of the other specific error codes described by the framework. 188 */ 189 int (*delay)(fwk_id_t dev_id, uint32_t microseconds); 190 191 /*! 192 * \brief Delay execution, waiting until a given condition is true or until 193 * a given timeout period has been exceeded, whichever occurs first. 194 * 195 * \note The calling thread is blocked until either condition has been met. 196 * 197 * \param dev_id Element identifier that identifies the timer device. 198 * \param microseconds Maximum amount of time, in microseconds, to wait for 199 * the given condition to be met. 200 * \param cond Pointer to the function that evaluates the condition and 201 * which returns a boolean value indicating if it has been met or not. 202 * The condition function is called repeatedly until it returns true, 203 * or until the timeout period has elapsed. 204 * \param data Pointer passed to the condition function when it is called. 205 * 206 * \retval ::FWK_SUCCESS The condition was met before the timeout period 207 * elapsed. 208 * \retval ::FWK_E_TIMEOUT The timeout period elapsed before the condition 209 * was met. 210 * \retval One of the other specific error codes described by the framework. 211 */ 212 int (*wait)(fwk_id_t dev_id, 213 uint32_t microseconds, 214 bool (*cond)(void*), 215 void *data); 216 217 /*! 218 * \brief Get the time difference, expressed in timer ticks, between the 219 * current timer counter value and the given timestamp. This represents 220 * the remaining number of ticks until the given timestamp is reached. 221 * 222 * \note If the given timestamp is in the past then the remaining_ticks is 223 * set to zero. 224 * 225 * \param dev_id Element identifier that identifies the timer device. 226 * \param timestamp Timestamp to compare to the current timer value. 227 * \param[out] remaining_ticks The remaining number of ticks before 228 * the timer value reaches the given timestamp. 229 * 230 * \retval ::FWK_SUCCESS Operation succeeded. 231 * \retval ::FWK_E_PARAM The remaining_ticks pointer was invalid. 232 * \retval One of the other specific error codes described by the framework. 233 * 234 * \note remaining_ticks is also a timestamp. 235 */ 236 int (*remaining)(fwk_id_t dev_id, 237 uint64_t timestamp, 238 uint64_t *remaining_ticks); 239 240 /*! 241 * \brief Get the number of ticks before the next alarm trigger of a given 242 * timer. 243 * 244 * \warning If the timer has no active alarm, \p remaining_ticks is not 245 * initialized. 246 * 247 * \param dev_id Element identifier that identifies the timer device. 248 * \param [out] has_alarm \c true if the timer has an active alarm, 249 * otherwise \c false. 250 * \param [out] remaining_ticks Number of ticks between now and the next 251 * alarm trigger of the timer identified by \p dev_id. 252 * 253 * \retval ::FWK_SUCCESS Operation succeeded. 254 * \retval ::FWK_E_PARAM One of the parameters is invalid. 255 * \retval ::FWK_E_DEVICE The timer driver failed. 256 * \return One of the other specific error codes described by the framework. 257 */ 258 int (*get_next_alarm_remaining)(fwk_id_t dev_id, 259 bool *has_alarm, 260 uint64_t *remaining_ticks); 261 }; 262 263 /*! 264 * \brief Alarm interface 265 */ 266 struct mod_timer_alarm_api { 267 /*! 268 * \brief Start an alarm so it will trigger after a specified time. 269 * 270 * \details When an alarm is triggered, \p callback is called. 271 * 272 * If the alarm is periodic, it will automatically be started again 273 * with the same time delay after it triggers. 274 * 275 * An alarm can be started multiple times without being stopped. In this 276 * case, internally, the alarm will be stopped then started again with 277 * the new configuration. 278 * 279 * \warning \p callback will be called from within an interrupt service 280 * routine. 281 * 282 * \param alarm_id Sub-element identifier of the alarm. 283 * \param milliseconds The time delay, given in milliseconds, until the 284 * alarm should trigger. 285 * \param type ::MOD_TIMER_ALARM_TYPE_ONCE or 286 * ::MOD_TIMER_ALARM_TYPE_PERIODIC. 287 * \param callback Pointer to the callback function. 288 * \param param Parameter given to the callback function when called. 289 * 290 * \pre \p alarm_id must be a valid sub-element alarm identifier that has 291 * previously been bound to. 292 * 293 * \retval ::FWK_E_ACCESS The function was called from an interrupt handler 294 * OR could not attain call context. 295 * \retval ::FWK_E_DEVICE The timer driver failed. 296 * \retval ::FWK_SUCCESS The alarm was started. 297 * \return One of the other specific error codes described by the framework. 298 */ 299 int (*start)(fwk_id_t alarm_id, 300 unsigned int milliseconds, 301 enum mod_timer_alarm_type type, 302 void (*callback)(uintptr_t param), 303 uintptr_t param); 304 305 /*! 306 * \brief Stop a previously started alarm. 307 * 308 * \details Stop an alarm that was previously started. This will prevent the 309 * alarm from triggering. This does not undo the binding of the alarm 310 * and it can be started again afterwards. 311 * 312 * \param alarm_id Sub-element identifier of the alarm item. 313 * 314 * \pre \p alarm_id must be a valid sub-element alarm identifier that has 315 * previously been bound to. 316 * 317 * \retval ::FWK_SUCCESS The alarm was stopped. 318 * \retval ::FWK_E_DEVICE The timer driver failed. 319 * \retval ::FWK_E_STATE The alarm was already stopped. 320 * \retval ::FWK_E_ACCESS The function was called from an interrupt handler 321 * different from the interrupt handler of the timer the alarm is 322 * associated to OR could not attain call context. 323 * \retval ::FWK_E_INIT The component has not been initialized. 324 * \return One of the other specific error codes described by the framework. 325 */ 326 int (*stop)(fwk_id_t alarm_id); 327 }; 328 329 /*! 330 * \} 331 */ 332 333 /*! 334 * \} 335 */ 336 337 #endif /* MOD_TIMER_H */ 338