1 /* 2 * Copyright (c) 2019 Arm Limited 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * \file systimer_armv8-m_drv.h 19 * 20 * \brief Driver for Armv8-M System Timer 21 * 22 * This System Timer is based on the 64-bit Armv8-M System Counter, 23 * generating the physical count for System Timer. 24 * 25 * Main features: 26 * - Disabling the timer doesn't stop counting, but it disables timer output 27 * signal, what might be a power saving option. 28 * - 1 interrupt signal, can be triggered by the 2 modes below 29 * Modes: 30 * 1. Normal mode 31 * For clearing the interrupt generated by normal mode, the Timer 32 * should be disabled. 33 * Views 34 * 1.1. 64-bit up-counting Compare view 35 * As soon as the physical up-counter reaches the set 36 * compare value, the interrupt status will be asserted. 37 * \ref systimer_armv8_m_set_compare_value 38 * \ref systimer_armv8_m_get_compare_value 39 40 * 1.2. 32-bit down-counting Timer view 41 * As soon as the down-counter timer reaches zero, 42 * the interrupt status will be asserted. 43 * Setting the down-counter timer value, sets the compare 44 * register by 45 * compare register = current counter + timer value 46 * \ref systimer_armv8_m_set_timer_value 47 * \ref systimer_armv8_m_get_timer_value 48 * 49 * 2. Auto-Increment mode 50 * - The auto-increment feature allows generation of Timer 51 * interrupt at regular intervals without the need for 52 * reprogramming the Timer after each interrupt and re-enabling 53 * the timer logic. 54 * - Auto-increment is working as a 64-bit up-counter, which is set 55 * by the 32-bit reload register. 56 * - If auto-increment mode is enabled, none of the normal modes' 57 * views can assert interrupt. * 58 * \ref systimer_armv8_m_get_autoinc_value 59 * \ref systimer_armv8_m_set_autoinc_reload 60 * \ref systimer_armv8_m_enable_autoinc 61 * \ref systimer_armv8_m_disable_autoinc 62 * \ref systimer_armv8_m_is_autoinc_enabled 63 * \ref systimer_armv8_m_clear_autoinc_interrupt 64 * \ref systimer_armv8_m_is_autoinc_implemented 65 * 66 */ 67 68 #ifndef __SYSTIMER_ARMV8_M_DRV_H__ 69 #define __SYSTIMER_ARMV8_M_DRV_H__ 70 71 #include <stdbool.h> 72 #include <stdint.h> 73 74 #ifdef __cplusplus 75 extern "C" { 76 #endif 77 78 #define SYSTIMER_ARMV8_M_REGISTER_BIT_WIDTH 32u 79 /*!< Armv8-M System Timer registers bit width */ 80 81 /** 82 * \brief Armv8-M System Timer device configuration structure 83 */ 84 struct systimer_armv8_m_dev_cfg_t { 85 const uint32_t base; 86 /*!< Armv8-M System Timer device base address */ 87 uint32_t default_freq_hz; 88 /*!< Default reported frequency in Hz */ 89 }; 90 91 /** 92 * \brief Armv8-M System Timer device data structure 93 */ 94 struct systimer_armv8_m_dev_data_t { 95 bool is_initialized; 96 }; 97 98 /** 99 * \brief Armv8-M System Timer device structure 100 */ 101 struct systimer_armv8_m_dev_t { 102 const struct systimer_armv8_m_dev_cfg_t* const cfg; 103 /*!< Armv8-M System Timer configuration structure */ 104 struct systimer_armv8_m_dev_data_t* const data; 105 /*!< Armv8-M System Timer data structure */ 106 }; 107 108 /** 109 * \brief Initializes timer to a known default state, which is: 110 * - timer is enabled 111 * - interrupt is disabled 112 * - auto-increment is disabled 113 * - reported timer frequency is set to default 114 * Init should be called prior to any other process and 115 * it's the caller's responsibility to follow proper call order. 116 * More than one call results fall through. 117 * 118 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 119 * 120 * \note This function doesn't check if dev is NULL. 121 */ 122 void systimer_armv8_m_init(struct systimer_armv8_m_dev_t* dev); 123 124 /** 125 * \brief Uninitializes timer to a known default state, which is: 126 * - timer is disabled 127 * - interrupt is disabled 128 * - auto-increment is disabled 129 * Init should be called prior to any other process and 130 * it's the caller's responsibility to follow proper call order. 131 * More than one call results fall through. 132 * 133 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 134 * 135 * \note This function doesn't check if dev is NULL. 136 */ 137 void systimer_armv8_m_uninit(struct systimer_armv8_m_dev_t* dev); 138 139 /** 140 * \brief Reads 64-bit physical counter value 141 * 142 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 143 * 144 * \return 64-bit counter value 145 * 146 * \note This function doesn't check if dev is NULL. 147 */ 148 uint64_t systimer_armv8_m_get_counter_value( 149 struct systimer_armv8_m_dev_t* dev); 150 151 /** 152 * \brief Sets 64-bit compare value 153 * As soon as the physical up-counter reaches this value, the interrupt 154 * condition will be asserted \ref systimer_armv8_m_is_interrupt_asserted 155 * 156 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 157 * \param[in] value 64-bit compare value 158 * 159 * \note This function doesn't check if dev is NULL. 160 */ 161 void systimer_armv8_m_set_compare_value( 162 struct systimer_armv8_m_dev_t* dev, 163 uint64_t value); 164 165 /** 166 * \brief Reads 64-bit compare value 167 * 168 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 169 * 170 * \return 64-bit compare value 171 * 172 * \note This function doesn't check if dev is NULL. 173 */ 174 uint64_t systimer_armv8_m_get_compare_value( 175 struct systimer_armv8_m_dev_t* dev); 176 177 /** 178 * \brief Sets frequency register in Hz 179 * Hardware does not interpret the value of the register, so it's only 180 * for software can discover the frequency of the system counter. 181 * 182 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 183 * \param[in] value frequency in Hz 184 * 185 * \note This function doesn't check if dev is NULL. 186 */ 187 void systimer_armv8_m_set_counter_freq( 188 struct systimer_armv8_m_dev_t* dev, 189 uint32_t value); 190 191 /** 192 * \brief Reads frequency register in Hz 193 * 194 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 195 * 196 * \return frequency in Hz 197 * 198 * \note This function doesn't check if dev is NULL. 199 */ 200 uint32_t systimer_armv8_m_get_counter_freq( 201 struct systimer_armv8_m_dev_t* dev); 202 203 /** 204 * \brief Sets 32-bit down-counter timer value 205 * 'Down-counter timer set' automatically sets the compare register by 206 * compare register = current counter + this timer value 207 * 208 * As soon as the timer value reaches zero, the interrupt condition will 209 * be asserted \ref systimer_armv8_m_is_interrupt_asserted. 210 * Reaching zero doesn't stop the timer. 211 * 212 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 213 * \param[in] value 32-bit timer value 214 * 215 * \note This function doesn't check if dev is NULL. 216 */ 217 void systimer_armv8_m_set_timer_value(struct systimer_armv8_m_dev_t* dev, 218 uint32_t value); 219 220 /** 221 * \brief Reads down-counter timer value 222 * 223 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 224 * 225 * \return 32-bit timer value 226 * 227 * \note This function doesn't check if dev is NULL. 228 */ 229 uint32_t systimer_armv8_m_get_timer_value( 230 struct systimer_armv8_m_dev_t* dev); 231 232 /** 233 * \brief Enables timer 234 * Enables timer output signal and interrupt status assertion 235 * \ref systimer_armv8_m_is_interrupt_asserted 236 * 237 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 238 * 239 * \note This function doesn't check if dev is NULL. 240 */ 241 void systimer_armv8_m_enable_timer(struct systimer_armv8_m_dev_t* dev); 242 243 /** 244 * \brief Disables timer 245 * Disables timer output signal. Interrupt status will be unknown 246 * \ref systimer_armv8_m_is_interrupt_asserted 247 * 248 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 249 * 250 * \note This function doesn't check if dev is NULL. 251 */ 252 void systimer_armv8_m_disable_timer(struct systimer_armv8_m_dev_t* dev); 253 254 /** 255 * \brief Polls timer enable status 256 * 257 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 258 * 259 * \return true if enabled, false otherwise 260 * 261 * \note This function doesn't check if dev is NULL. 262 */ 263 bool systimer_armv8_m_is_timer_enabled( 264 struct systimer_armv8_m_dev_t* dev); 265 266 /** 267 * \brief Enables timer interrupt 268 * 269 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 270 * 271 * \note This function doesn't check if dev is NULL. 272 */ 273 void systimer_armv8_m_enable_interrupt( 274 struct systimer_armv8_m_dev_t* dev); 275 276 /** 277 * \brief Disables timer interrupt 278 * 279 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 280 * 281 * \note This function doesn't check if dev is NULL. 282 */ 283 void systimer_armv8_m_disable_interrupt( 284 struct systimer_armv8_m_dev_t* dev); 285 286 /** 287 * \brief Polls timer interrupt enable status 288 * 289 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 290 * 291 * \return true if enabled, false otherwise 292 * 293 * \note This function doesn't check if dev is NULL. 294 */ 295 bool systimer_armv8_m_is_interrupt_enabled( 296 struct systimer_armv8_m_dev_t* dev); 297 298 /** 299 * \brief Polls timer interrupt status 300 * It's asserted if 301 * 1. Auto-Inc is disabled and counter reaches compare value 302 * OR 303 * 2. Auto-Inc is enabled and counter reaches auto-inc value 304 * 305 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 306 * 307 * \return true if asserted, false otherwise 308 * 309 * \note This function doesn't check if dev is NULL. 310 */ 311 bool systimer_armv8_m_is_interrupt_asserted( 312 struct systimer_armv8_m_dev_t* dev); 313 314 /** 315 * \brief Reads auto-increment value 316 * This value is automatically calculated by 317 * auto-inc = current counter + auto-inc reload 318 * 319 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 320 * 321 * \return 64-bit auto-increment value 322 * 323 * \note This function doesn't check if dev is NULL. 324 */ 325 uint64_t systimer_armv8_m_get_autoinc_value( 326 struct systimer_armv8_m_dev_t* dev); 327 328 /** 329 * \brief Sets 32-bit auto-increment reload value 330 * Auto-Inc value is automatically calculated by adding this reload value 331 * to the current counter. 332 * If the counter reaches auto-inc value, interrupt status is asserted 333 * and auto-inc value is automatically set by current reload. 334 * 335 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 336 * \param[in] value 32-bit reload value 337 * 338 * \note This function doesn't check if dev is NULL. 339 */ 340 void systimer_armv8_m_set_autoinc_reload( 341 struct systimer_armv8_m_dev_t* dev, 342 uint32_t value); 343 344 /** 345 * \brief Reads auto-increment reload value 346 * 347 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 348 * 349 * \return 32-bit auto-increment reload value 350 * 351 * \note This function doesn't check if dev is NULL. 352 */ 353 uint32_t systimer_armv8_m_get_autoinc_reload( 354 struct systimer_armv8_m_dev_t* dev); 355 356 /** 357 * \brief Enables auto-increment mode 358 * 359 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 360 * 361 * \note This function doesn't check if dev is NULL. 362 */ 363 void systimer_armv8_m_enable_autoinc(struct systimer_armv8_m_dev_t* dev); 364 365 /** 366 * \brief Disables auto-increment mode 367 * 368 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 369 * 370 * \note This function doesn't check if dev is NULL. 371 */ 372 void systimer_armv8_m_disable_autoinc(struct systimer_armv8_m_dev_t* dev); 373 374 /** 375 * \brief Polls auto-increment enable status 376 * 377 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 378 * 379 * \return true if enabled, false otherwise 380 * 381 * \note This function doesn't check if dev is NULL. 382 */ 383 bool systimer_armv8_m_is_autoinc_enabled( 384 struct systimer_armv8_m_dev_t* dev); 385 386 /** 387 * \brief Clears auto-increment mode interrupt flag 388 * 389 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 390 * 391 * \note This function doesn't check if dev is NULL. 392 */ 393 void systimer_armv8_m_clear_autoinc_interrupt( 394 struct systimer_armv8_m_dev_t* dev); 395 396 /** 397 * \brief Polls auto-increment implementation status 398 * 399 * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t 400 * 401 * \return true if implemented, false otherwise 402 * 403 * \note This function doesn't check if dev is NULL. 404 */ 405 bool systimer_armv8_m_is_autoinc_implemented( 406 struct systimer_armv8_m_dev_t* dev); 407 408 #ifdef __cplusplus 409 } 410 #endif 411 #endif /* __SYSTIMER_ARMV8_M_DRV_H__ */ 412