1 /*******************************************************************************
2  * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  *
24  * PolarFire SoC Microprocessor Subsystem (MSS) Timer bare metal software driver
25  * public API.
26  */
27 /*=========================================================================*//**
28   @mainpage PolarFire SoC MSS Timer Bare Metal Driver.
29 
30   @section intro_sec Introduction
31   The PolarFire SoC Microprocessor Subsystem (MSS) includes a timer hardware
32   block which can be used as two independent 32-bits timers or as a single
33   64-bits timer in periodic or one-shot mode.
34 
35   This driver provides a set of functions for controlling the MSS timer as part
36   of a bare metal system where no operating system is available. These drivers
37   can be adapted for use as part of an operating system but the implementation
38   of the adaptation layer between this driver and the operating system's driver
39   model is outside the scope of this driver.
40 
41   @section theory_op Theory of Operation
42   The PolarFire SoC MSS Timer can be used in one of two mutually exclusive modes
43   either as a single 64-bits timer or as two independent 32-bits timers. The MSS
44   Timer can be used in either periodic mode or one-shot mode. A timer configured
45   for periodic mode operations will generate an interrupt and reload its
46   down-counter when it reaches 0. The timer will then continue decrementing from
47   its reload value without waiting for the interrupt to be cleared. A timer
48   configured for one-shot mode will only generate an interrupt once when its
49   down-counter reaches 0. It must be explicitly reloaded to start decrementing
50   again.
51 
52   The MSS Timer driver functions are grouped into the following categories:
53     - Initialization and Configuration
54     - Timer control
55     - Interrupt control
56 
57   The MSS Timer driver provides three initialization functions:
58     - MSS_TIM1_init()
59     - MSS_TIM2_init()
60     - MSS_TIM64_init()
61 
62   The MSS Timer driver is initialized through calls to these functions and at
63   least one of them must be called before any other MSS Timer driver functions
64   can be called.
65   You should only use the MSS_TIM1_init() and MSS_TIM2_init() functions if you
66   intend to use the timer in 32-bits mode. Use the MSS_TIM64_init() function is
67   you intend to use the MSS Timer as a single 64-bits timer. The initialization
68   functions take a single parameter specifying the operating mode of the timer
69   being initialized.
70 
71   Once initialized a timer can be controlled using the following functions:
72     - MSS_TIM1_load_immediate()
73     - MSS_TIM1_load_background()
74     - MSS_TIM1_get_current_value()
75     - MSS_TIM1_start()
76     - MSS_TIM1_stop()
77     - MSS_TIM2_load_immediate()
78     - MSS_TIM2_load_background()
79     - MSS_TIM2_get_current_value()
80     - MSS_TIM2_start()
81     - MSS_TIM2_stop()
82     - MSS_TIM64_load_immediate()
83     - MSS_TIM64_load_background()
84     - MSS_TIM64_get_current_value()
85     - MSS_TIM64_start()
86     - MSS_TIM64_stop()
87 
88   Timer interrupts are controlled using the following functions:
89     - MSS_TIM1_enable_irq()
90     - MSS_TIM1_disable_irq()
91     - MSS_TIM1_clear_irq()
92     - MSS_TIM2_enable_irq()
93     - MSS_TIM2_disable_irq()
94     - MSS_TIM2_clear_irq()
95     - MSS_TIM64_enable_irq()
96     - MSS_TIM64_disable_irq()
97     - MSS_TIM64_clear_irq()
98 
99   The function prototypes for the timer interrupt handlers are:
100     - void Timer1_IRQHandler( void )
101     - void Timer2_IRQHandler( void )
102 
103   Entries for these interrupt handlers are provided in the PolarFire SoC MPFS
104   HAL vector table. To add a Timer 1 interrupt handler, you must implement a
105   Timer1_IRQHandler( ) function as part of your application code. To add a
106   Timer 2 interrupt handler, you must implement a Timer2_IRQHandler( ) function
107   as part of your application code. When using the MSS Timer as a 64-bit timer,
108   you must implement a Timer1_IRQHandler( ) function as part of your
109   application code. The Timer 2 interrupt is not used when the MSS Timer is
110   configured as a 64-bit timer.
111 
112  *//*=========================================================================*/
113 #ifndef MSS_TIMER_H_
114 #define MSS_TIMER_H_
115 
116 #include "mpfs_hal/mss_hal.h"
117 #include "mss_timer_regs.h"
118 
119 #ifdef __cplusplus
120 extern "C" {
121 #endif
122 
123  /*****************************************************************************/
124  /*                         Peripheral declaration                            */
125  /*****************************************************************************/
126 
127  #define TIMER_LO                      ((TIMER_TypeDef *) TIMER_LO_BASE)
128  #define TIMER_HI                      ((TIMER_TypeDef*) TIMER_HI_BASE)
129 
130 /*-------------------------------------------------------------------------*//**
131  * Timer mode selection. This enumeration is used to select between the two
132  * possible timer modes of operation: periodic and one-shot mode. It is used as
133  * an argument to the MSS_TIM1_init(), MSS_TIM2_init() and MSS_TIM64_init()
134  * functions.
135  * MSS_TIMER_PERIODIC_MODE:
136  *  In periodic mode the timer generates interrupts at constant intervals. On
137  *  reaching zero, the timer's counter is reloaded with a value held in a
138  *  register and begins counting down again.
139  * MSS_TIMER_ONE_SHOT_MODE:
140  *  The timer generates a single interrupt in this mode. On reaching zero, the
141  *  timer's counter halts until reprogrammed by the user.
142  */
143 typedef enum __mss_timer_mode
144 {
145     MSS_TIMER_PERIODIC_MODE = 0,//!< MSS_TIMER_PERIODIC_MODE
146     MSS_TIMER_ONE_SHOT_MODE = 1 //!< MSS_TIMER_ONE_SHOT_MODE
147 } mss_timer_mode_t;
148 
149 /*-------------------------------------------------------------------------*//**
150  * Timer operation mask defines.
151  */
152 /* Timer 1 interrupt enable bits */
153 #define TIM1_INTEN_MASK     0x00000004u
154 
155 /* Timer 1 Mode bits */
156 #define TIM1_MODE_SHIFT     1u
157 #define TIM1_MODE_MASK      0x00000002u
158 
159 /* Timer 1 enable bits */
160 #define TIM1_ENABLE_MASK    0x00000001u
161 
162 /* Timer 2 interrupt enable bits */
163 #define TIM2_INTEN_MASK     0x00000004u
164 
165 /* Timer 2 Mode bits */
166 #define TIM2_MODE_SHIFT     1u
167 #define TIM2_MODE_MASK      0x00000002u
168 
169 /* Timer 2 enable bits */
170 #define TIM2_ENABLE_MASK    0x00000001u
171 
172 /* Timer 64 interrupt enable bits */
173 #define TIM64_INTEN_MASK    0x00000004u
174 
175 /* Timer 64 mode bits */
176 #define TIM64_MODE_SHIFT    1u
177 #define TIM64_MODE_MASK     0x00000002u
178 
179 /* Timer 64 enable bits */
180 #define TIM64_ENABLE_MASK   0x00000001u
181 
182 static uint32_t readvalue[52] = {0};
183 
184 /*-------------------------------------------------------------------------*//**
185   The MSS_TIM1_init() function initializes the MSS Timer block for use as a
186   32-bit timer and selects the operating mode for Timer 1. The MSS Timer block
187   is out of reset before executing this function. The MSS_TIM1_init() function
188   stops Timer 1, disables its interrupt, and sets the Timer 1 operating mode.
189 
190   @param timer
191     The timer parameter specifies the Timer block to configure.
192 
193   @param mode
194     The mode parameter specifies whether the timer will operate in periodic or
195     one-shot mode. Allowed values for this parameter are:
196         - MSS_TIMER_PERIODIC_MODE
197         - MSS_TIMER_ONE_SHOT_MODE
198 
199   Note:The MSS Timer block cannot be used both as a 64-bit and 32-bit timer.
200        Calling MSS_TIM1_init() will overwrite any previous configuration
201        of the MSS Timer as a 64-bit timer.
202  */
203 static inline void
MSS_TIM1_init(TIMER_TypeDef * timer,mss_timer_mode_t mode)204 MSS_TIM1_init(TIMER_TypeDef* timer, mss_timer_mode_t mode)
205 {
206     PLIC_DisableIRQ(TIMER1_PLIC);               /* Disable timer 1 irq */
207 
208     timer->TIM64_MODE = 0u;                     /* switch to 32 bits mode */
209     readvalue[1] = timer->TIM64_MODE;
210 
211     /* Disable timer and interrupt and set mode (continuous/one-shot) */
212     timer->TIM1_CTRL = TIM1_MODE_MASK & ((uint32_t)mode << TIM1_MODE_SHIFT);
213     readvalue[2] = timer->TIM1_CTRL;
214 
215     timer->TIM1_RIS = 1u;                       /* clear timer 1 interrupt */
216     readvalue[3] = timer->TIM1_RIS;
217 }
218 
219 /*-------------------------------------------------------------------------*//**
220   The MSS_TIM1_start() function enables Timer 1 and starts its down-counter
221   decrementing from the load_value specified in previous calls to the
222   MSS_TIM1_load_immediate() or MSS_TIM1_load_background() functions.
223 
224   @param timer
225     The timer parameter specifies the Timer block to configure.
226 
227   Note: The MSS_TIM1_start() function is also used to resume the down-counter
228         if previously stopped using the MSS_TIM1_stop() function.
229  */
230 static inline void
MSS_TIM1_start(TIMER_TypeDef * timer)231 MSS_TIM1_start(TIMER_TypeDef* timer)
232 {
233     timer->TIM1_CTRL |= TIM1_ENABLE_MASK;
234 }
235 
236 /*-------------------------------------------------------------------------*//**
237   The MSS_TIM1_stop() function disables Timer 1 and stops its down-counter
238   decrementing.
239 
240   @param timer
241     The timer parameter specifies the Timer block to configure.
242 
243  */
244 static inline void
MSS_TIM1_stop(TIMER_TypeDef * timer)245 MSS_TIM1_stop(TIMER_TypeDef* timer)
246 {
247     timer->TIM1_CTRL &= ~((uint32_t)TIM1_ENABLE_MASK);    /* disable timer */
248 }
249 
250 /*-------------------------------------------------------------------------*//**
251   The MSS_TIM1_get_current_value() returns the current value of the Timer 1
252   down-counter.
253 
254   @param timer
255     The timer parameter specifies the Timer block to configure.
256 
257   @return
258     This function returns the 32-bits current value of the Timer 1 down-counter.
259  */
260 static inline uint32_t
MSS_TIM1_get_current_value(TIMER_TypeDef * timer)261 MSS_TIM1_get_current_value(TIMER_TypeDef* timer)
262 {
263     return timer->TIM1_VAL;
264 }
265 
266 /*-------------------------------------------------------------------------*//**
267   The MSS_TIM1_load_immediate() function loads the value passed by the
268   load_value parameter into the Timer 1 down-counter. The counter will
269   decrement immediately from this value once Timer 1 is enabled. The MSS
270   Timer will generate an interrupt when the counter reaches zero, if Timer 1
271   interrupts are enabled. This function is intended to be used when Timer 1
272   is configured for one-shot mode to time a single delay.
273 
274   Note: The value passed by the load_value parameter is loaded immediately
275         into the down-counter regardless of whether Timer 1 is operating in
276         periodic or one-shot mode.
277 
278   @param timer
279     The timer parameter specifies the Timer block to configure.
280 
281   @param load_value
282     The load_value parameter specifies the value from which the Timer 1
283     down-counter will start decrementing from.
284  */
285 static inline void
MSS_TIM1_load_immediate(TIMER_TypeDef * timer,uint32_t load_value)286 MSS_TIM1_load_immediate(TIMER_TypeDef* timer, uint32_t load_value)
287 {
288     timer->TIM1_LOADVAL = load_value;
289 }
290 
291 /*-------------------------------------------------------------------------*//**
292   The MSS_TIM1_load_background() function is used to specify the value that will
293   be reloaded into the Timer 1 down-counter the next time the counter reaches
294   zero. This function is typically used when Timer 1 is configured for periodic
295   mode operation to select or change the delay period between the interrupts
296   generated by Timer 1.
297 
298   @param timer
299     The timer parameter specifies the Timer block to configure.
300 
301   @param load_value
302     The load_value parameter specifies the value that will be loaded into the
303     Timer 1 down-counter the next time the down-counter reaches zero. The Timer
304     1 down-counter will start decrementing from this value after the current
305     count expires.
306  */
307 static inline void
MSS_TIM1_load_background(TIMER_TypeDef * timer,uint32_t load_value)308 MSS_TIM1_load_background(TIMER_TypeDef* timer, uint32_t load_value)
309 {
310     timer->TIM1_BGLOADVAL = load_value;
311 }
312 
313 /*-------------------------------------------------------------------------*//**
314   The MSS_TIM1_enable_irq() function is used to enable interrupt generation for
315   Timer 1. This function also enables the interrupt in the RISC-V PLIC. The
316   Timer1_IRQHandler() function will be called when a Timer 1 interrupt occurs.
317 
318   Note: A Timer1_IRQHandler() default implementation is defined, with weak
319         linkage, in the MPFS HAL. You must provide your own implementation of
320         the Timer1_IRQHandler() function, which will override the default
321         implementation, to suit your application.
322 
323   @param timer
324     The timer parameter specifies the Timer block to configure.
325 
326 */
327 static inline void
MSS_TIM1_enable_irq(TIMER_TypeDef * timer)328 MSS_TIM1_enable_irq(TIMER_TypeDef* timer)
329 {
330     timer->TIM1_CTRL |= TIM1_INTEN_MASK;
331     readvalue[8] = timer->TIM1_CTRL;
332     PLIC_EnableIRQ(TIMER1_PLIC);
333 }
334 
335 /*-------------------------------------------------------------------------*//**
336   The MSS_TIM1_disable_irq() function is used to disable interrupt generation for
337   Timer 1. This function also disables the interrupt in the RISC-V PLIC.
338 
339   @param timer
340     The timer parameter specifies the Timer block to configure.
341 
342  */
343 static inline void
MSS_TIM1_disable_irq(TIMER_TypeDef * timer)344 MSS_TIM1_disable_irq(TIMER_TypeDef* timer)
345 {
346     timer->TIM1_CTRL &= ~((uint32_t)TIM1_INTEN_MASK);
347     PLIC_DisableIRQ(TIMER1_PLIC);               /* Disable timer 1 irq */
348 }
349 
350 /*-------------------------------------------------------------------------*//**
351   The MSS_TIM1_clear_irq() function is used to clear a pending interrupt from
352   Timer 1. This function also clears the interrupt in the RISC-V PLIC.
353 
354   Note:You must call the MSS_TIM1_clear_irq() function as part of your
355        implementation of the Timer1_IRQHandler() Timer 1 interrupt service
356        routine (ISR) in order to prevent the same interrupt event
357        retriggering a call to the ISR.
358 
359   @param timer
360     The timer parameter specifies the Timer block to configure.
361 
362  */
363 static inline void
MSS_TIM1_clear_irq(TIMER_TypeDef * timer)364 MSS_TIM1_clear_irq(TIMER_TypeDef* timer)
365 {
366     timer->TIM1_RIS = 1u;
367 }
368 
369 /*-------------------------------------------------------------------------*//**
370   The MSS_TIM2_init() function initializes the MSS Timer block for use as a
371   32-bit timer and selects the operating mode for Timer 2. The MSS Timer block
372   is already out of reset before executing MSS_TIM2_init() function. This
373   function stops Timer 2, disables its interrupt and sets the Timer 2 operating
374   mode.
375 
376   Note:The MSS Timer block cannot be used both as a 64-bit and 32-bit timer.
377        Calling MSS_TIM2_init() will overwrite any previous configuration of the
378        MSS Timer as a 64-bit timer.
379 
380   @param timer
381     The timer parameter specifies the Timer block to configure.
382 
383   @param mode
384     The mode parameter specifies whether the timer will operate in periodic or
385     one-shot mode. Allowed values for this parameter are:
386         - MSS_TIMER_PERIODIC_MODE
387         - MSS_TIMER_ONE_SHOT_MODE
388  */
389 static inline void
MSS_TIM2_init(TIMER_TypeDef * timer,mss_timer_mode_t mode)390 MSS_TIM2_init(TIMER_TypeDef* timer, mss_timer_mode_t mode)
391 {
392     PLIC_DisableIRQ(TIMER2_PLIC);               /* Disable timer 2 irq */
393     timer->TIM64_MODE = 0u;                     /* switch to 32 bits mode */
394 
395     /* Disable timer and interrupt. Set mode (continuous/one-shot) */
396     timer->TIM2_CTRL = TIM2_MODE_MASK & ((uint32_t)mode << TIM2_MODE_SHIFT);
397 
398     timer->TIM2_RIS = 1u;                       /* clear timer 2 interrupt */
399 }
400 
401 /*-------------------------------------------------------------------------*//**
402   The MSS_TIM2_start() function enables Timer 2 and  starts its down-counter
403   decrementing from the load_value specified in previous calls to the
404   MSS_TIM2_load_immediate() or MSS_TIM2_load_background() functions.
405 
406   @param timer
407     The timer parameter specifies the Timer block to configure.
408 
409   Note:The MSS_TIM2_start() function is also used to resume the down-counter
410        if previously stopped using the MSS_TIM2_stop() function.
411  */
412 static inline void
MSS_TIM2_start(TIMER_TypeDef * timer)413 MSS_TIM2_start(TIMER_TypeDef* timer)
414 {
415     timer->TIM2_CTRL |= TIM2_ENABLE_MASK;     /* enable timer */
416 }
417 
418 /*-------------------------------------------------------------------------*//**
419   The MSS_TIM2_stop() function disables Timer 2 and stops its down-counter
420   decrementing.
421 
422   @param timer
423     The timer parameter specifies the Timer block to configure.
424  */
425 static inline void
MSS_TIM2_stop(TIMER_TypeDef * timer)426 MSS_TIM2_stop(TIMER_TypeDef* timer)
427 {
428     timer->TIM2_CTRL &= ~((uint32_t)TIM2_ENABLE_MASK);    /* disable timer */
429 }
430 
431 /*-------------------------------------------------------------------------*//**
432   The MSS_TIM2_get_current_value() returns the current value of the Timer 2
433   down-counter.
434 
435   @param timer
436     The timer parameter specifies the Timer block to configure.
437  */
438 static inline uint32_t
MSS_TIM2_get_current_value(TIMER_TypeDef * timer)439 MSS_TIM2_get_current_value(TIMER_TypeDef* timer)
440 {
441     return timer->TIM2_VAL;
442 }
443 
444 /*-------------------------------------------------------------------------*//**
445   The MSS_TIM2_load_immediate() function loads the value passed by the
446   load_value parameter into the Timer 2 down-counter. The counter will
447   decrement immediately from this value once Timer 2 is enabled. The MSS Timer
448   will generate an interrupt when the counter reaches zero if Timer 2
449   interrupts are enabled. This function is intended to be used when Timer 2
450   is configured for one-shot mode to time a single delay.
451 
452   Note:The value passed by the load_value parameter is loaded immediately into
453        the down-counter regardless of whether Timer 2 is operating in periodic
454        or one-shot mode.
455 
456   @param timer
457     The timer parameter specifies the Timer block to configure.
458 
459   @param load_value
460     The load_value parameter specifies the value from which the Timer 2
461     down-counter will start decrementing.
462  */
463 static inline void
MSS_TIM2_load_immediate(TIMER_TypeDef * timer,uint32_t load_value)464 MSS_TIM2_load_immediate(TIMER_TypeDef* timer, uint32_t load_value)
465 {
466     timer->TIM2_LOADVAL = load_value;
467 }
468 
469 /*-------------------------------------------------------------------------*//**
470   The MSS_TIM2_load_background() function is used to specify the value that will
471   be reloaded into the Timer 2 down-counter the next time the counter reaches
472   zero. This function is typically used when Timer 2 is configured for periodic
473   mode operation to select or change the delay period between the interrupts
474   generated by Timer 2.
475 
476   @param timer
477     The timer parameter specifies the Timer block to configure.
478 
479   @param load_value
480     The load_value parameter specifies the value that will be loaded into the
481     Timer 2 down-counter the next time the down-counter reaches zero. The Timer
482     2 down-counter will start decrementing from this value after the current
483     count expires.
484  */
485 static inline void
MSS_TIM2_load_background(TIMER_TypeDef * timer,uint32_t load_value)486 MSS_TIM2_load_background(TIMER_TypeDef* timer, uint32_t load_value)
487 {
488     timer->TIM2_BGLOADVAL = load_value;
489 }
490 
491 /*-------------------------------------------------------------------------*//**
492   The MSS_TIM2_enable_irq() function is used to enable interrupt generation for
493   Timer 2. This function also enables the interrupt in the RISC-V PLIC. The
494   Timer2_IRQHandler() function will be called when a Timer 2 interrupt occurs.
495 
496   Note:A Timer2_IRQHandler() default implementation is defined, with weak
497        linkage, in the MPFS HAL. You must provide your own implementation of
498        the Timer2_IRQHandler() function, which will override the default
499        implementation, to suit your application.
500 
501   @param timer
502     The timer parameter specifies the Timer block to configure.
503  */
504 static inline void
MSS_TIM2_enable_irq(TIMER_TypeDef * timer)505 MSS_TIM2_enable_irq(TIMER_TypeDef* timer)
506 {
507     timer->TIM2_CTRL |= TIM2_INTEN_MASK;
508     PLIC_EnableIRQ(TIMER2_PLIC);
509 }
510 
511 /*-------------------------------------------------------------------------*//**
512   The MSS_TIM2_disable_irq() function is used to disable interrupt generation for
513   Timer 2. This function also disables the interrupt in the RISC-V PLIC.
514 
515   @param timer
516     The timer parameter specifies the Timer block to configure.
517  */
518 static inline void
MSS_TIM2_disable_irq(TIMER_TypeDef * timer)519 MSS_TIM2_disable_irq(TIMER_TypeDef* timer)
520 {
521     timer->TIM2_CTRL &=  ~((uint32_t)TIM2_INTEN_MASK);
522     PLIC_DisableIRQ(TIMER2_PLIC);               /* Disable timer 2 irq */
523 }
524 
525 /*-------------------------------------------------------------------------*//**
526   The MSS_TIM2_clear_irq() function is used to clear a pending interrupt from
527   Timer 2. This function also clears the interrupt in the RISC-V PLIC.
528 
529   Note:You must call the MSS_TIM2_clear_irq() function as part of your
530        implementation of the Timer2_IRQHandler() Timer 2 interrupt service
531        routine (ISR) in order to prevent the same interrupt event retriggering
532        a call to the ISR.
533 
534   @param timer
535     The timer parameter specifies the Timer block to configure.
536 
537  */
538 static inline void
MSS_TIM2_clear_irq(TIMER_TypeDef * timer)539 MSS_TIM2_clear_irq(TIMER_TypeDef* timer)
540 {
541     timer->TIM2_RIS = 1u;
542 }
543 
544 /*-------------------------------------------------------------------------*//**
545   The MSS_TIM64_init() function initializes the MSS Timer block for use as a
546   single 64-bit timer and selects the operating mode of the timer. The MSS Timer
547   block is already out of reset before executing MSS_TIM64_init() function.
548   This function stops the timer, disables its interrupts, and sets the timer's
549   operating mode.
550 
551   Note:The MSS Timer block cannot be used both as a 64-bit and 32-bit timer.
552        Calling MSS_TIM64_init() will overwrite any previous configuration of the
553        MSS Timer as a 32-bit timer.
554 
555   @param timer
556     The timer parameter specifies the Timer block to configure.
557 
558   @param mode
559     The mode parameter specifies whether the timer will operate in periodic or
560     one-shot mode. Allowed values for this parameter are:
561         - MSS_TIMER_PERIODIC_MODE
562         - MSS_TIMER_ONE_SHOT_MODE
563  */
564 static inline void
MSS_TIM64_init(TIMER_TypeDef * timer,mss_timer_mode_t mode)565 MSS_TIM64_init(TIMER_TypeDef* timer, mss_timer_mode_t mode)
566 {
567     PLIC_DisableIRQ(TIMER1_PLIC);               /* Disable timer 1 irq */
568     PLIC_DisableIRQ(TIMER2_PLIC);               /* Disable timer 2 irq */
569 
570     timer->TIM64_MODE = 1u;                     /* switch to 64 bits mode */
571 
572     /* Disable timer and interrupt and set mode (continuous/one-shot) */
573     timer->TIM64_CTRL = TIM64_MODE_MASK & ((uint32_t)mode << TIM64_MODE_SHIFT);
574 
575     timer->TIM1_RIS = 1u;                   /* clear timer 1 interrupt */
576     timer->TIM2_RIS = 1u;                   /* clear timer 2 interrupt */
577 }
578 
579 /*-------------------------------------------------------------------------*//**
580   The MSS_TIM64_start() function enables the 64-bit timer and starts its
581   down-counter decrementing from the load_value specified in previous calls to
582   the MSS_TIM64_load_immediate() or MSS_TIM64_load_background() functions.
583 
584   Note: The MSS_TIM64_start() function is also used to resume the down-counter
585         if previously stopped using the MSS_TIM64_stop() function.
586 
587   @param timer
588     The timer parameter specifies the Timer block to configure.
589  */
590 static inline void
MSS_TIM64_start(TIMER_TypeDef * timer)591 MSS_TIM64_start(TIMER_TypeDef* timer)
592 {
593     timer->TIM64_CTRL |= TIM64_ENABLE_MASK;   /* enable timer */
594 }
595 
596 /*-------------------------------------------------------------------------*//**
597   The MSS_TIM64_stop() function disables the 64-bit timer and stops its
598   down-counter decrementing.
599 
600   @param timer
601     The timer parameter specifies the Timer block to configure.
602  */
603 static inline void
MSS_TIM64_stop(TIMER_TypeDef * timer)604 MSS_TIM64_stop(TIMER_TypeDef* timer)
605 {
606     timer->TIM64_CTRL &= ~((uint32_t)TIM64_ENABLE_MASK);    /* disable timer */
607 }
608 
609 /*-------------------------------------------------------------------------*//**
610   The MSS_TIM64_get_current_value() is used to read the current value of the
611   64-bit timer down-counter.
612 
613   @param timer
614     The timer parameter specifies the Timer block to configure.
615 
616   @param load_value_u
617     The load_value_u parameter is a pointer to a 32-bit variable where the upper
618     32 bits of the current value of the 64-bit timer down-counter will be copied.
619 
620   @param load_value_l
621     The load_value_l parameter is a pointer to a 32-bit variable where the lower
622     32 bits of the current value of the 64-bit timer down-counter will be copied.
623 
624   Example:
625   @code
626     uint32_t current_value_u = 0;
627     uint32_t current_value_l = 0;
628     MSS_TIM64_get_current_value( &current_value_u, &current_value_l );
629   @endcode
630  */
631 static inline void
MSS_TIM64_get_current_value(TIMER_TypeDef * timer,uint32_t * load_value_u,uint32_t * load_value_l)632 MSS_TIM64_get_current_value
633 (
634     TIMER_TypeDef* timer,
635     uint32_t * load_value_u,
636     uint32_t * load_value_l
637 )
638 {
639     *load_value_l = timer->TIM64_VAL_L;
640     *load_value_u = timer->TIM64_VAL_U;
641 }
642 
643 /*-------------------------------------------------------------------------*//**
644   The MSS_TIM64_load_immediate() function loads the values passed by the
645   load_value_u and load_value_l parameters into the 64-bit timer down-counter.
646   The counter will decrement immediately from the concatenated 64-bit value once
647   the 64-bit timer is enabled. The MSS Timer will generate an interrupt when the
648   counter reaches zero if 64-bit timer interrupts are enabled. This function is
649   intended to be used when the 64-bit timer is configured for one-shot mode to
650   time a single delay.
651 
652   Note: The value passed by the load_value parameter is loaded immediately into
653         the down-counter regardless of whether the 64-bit timer is operating in
654         periodic or one-shot mode.
655 
656   @param timer
657     The timer parameter specifies the Timer block to configure.
658 
659   @param load_value_u
660     The load_value_u parameter specifies the upper 32 bits of the 64-bit timer
661     load value from which the 64-bit timer down-counter will start decrementing.
662 
663   @param load_value_l
664     The load_value_l parameter specifies the lower 32 bits of the 64-bit timer
665     load value from which the 64-bit timer down-counter will start decrementing.
666  */
667 static inline void
MSS_TIM64_load_immediate(TIMER_TypeDef * timer,uint32_t load_value_u,uint32_t load_value_l)668 MSS_TIM64_load_immediate
669 (
670     TIMER_TypeDef* timer,
671     uint32_t load_value_u,
672     uint32_t load_value_l
673 )
674 {
675     timer->TIM64_LOADVAL_U = load_value_u;
676     timer->TIM64_LOADVAL_L = load_value_l;
677 }
678 
679 /*-------------------------------------------------------------------------*//**
680   The MSS_TIM64_load_background() function is used to specify the 64-bit value
681   that will be reloaded into the 64-bit timer down-counter the next time the
682   counter reaches zero. This function is typically used when the 64-bit timer is
683   configured for periodic mode operation to select or change the delay period
684   between the interrupts generated by the 64-bit timer.
685 
686   @param timer
687     The timer parameter specifies the Timer block to configure.
688 
689   @param load_value_u
690     The load_value_u parameter specifies the upper 32 bits of the 64-bit timer
691     load value. The concatenated 64-bit value formed from load_value_u and
692     load_value_l will be loaded into the 64-bit timer down-counter the next
693     time the down-counter reaches zero. The 64-bit timer down-counter will start
694     decrementing from the concatenated 64-bit value after the current count
695     expires.
696 
697   @param load_value_l
698     The load_value_l parameter specifies the lower 32 bits of the 64-bit timer
699     load value. The concatenated 64-bit value formed from load_value_u and
700     load_value_l will be loaded into the 64-bit timer down-counter the next time
701     the down-counter reaches zero. The 64-bit timer down-counter will start
702     decrementing from the concatenated 64-bit value after the current count
703     expires.
704  */
705 static inline void
MSS_TIM64_load_background(TIMER_TypeDef * timer,uint32_t load_value_u,uint32_t load_value_l)706 MSS_TIM64_load_background
707 (
708     TIMER_TypeDef* timer,
709     uint32_t load_value_u,
710     uint32_t load_value_l
711 )
712 {
713     timer->TIM64_BGLOADVAL_U = load_value_u;
714     timer->TIM64_BGLOADVAL_L = load_value_l;
715 }
716 
717 /*-------------------------------------------------------------------------*//**
718   The MSS_TIM64_enable_irq() function is used to enable interrupt generation for
719   the 64-bit timer. This function also enables the interrupt in the RISC-V PLIC.
720   The Timer1_IRQHandler() function will be called when a 64-bit timer interrupt
721   occurs.
722 
723   Note: A Timer1_IRQHandler() default implementation is defined, with weak
724         linkage, in the MPFS HAL. You must provide your own implementation of
725         the Timer1_IRQHandler() function, which will override the default
726         implementation, to suit your application.
727 
728   Note: The MSS_TIM64_enable_irq() function enables and uses Timer 1 interrupts
729         for the 64-bit timer. Timer 2 interrupts remain disabled.
730 
731   @param timer
732     The timer parameter specifies the Timer block to configure.
733 
734  */
735 static inline void
MSS_TIM64_enable_irq(TIMER_TypeDef * timer)736 MSS_TIM64_enable_irq(TIMER_TypeDef* timer)
737 {
738     timer->TIM64_CTRL |= TIM64_INTEN_MASK;
739     PLIC_EnableIRQ(TIMER1_PLIC);
740 }
741 
742 /*-------------------------------------------------------------------------*//**
743   The MSS_TIM64_disable_irq() function is used to disable interrupt generation
744   for the 64-bit timer. This function also disables the interrupt in the RISC-V
745   PLIC.
746 
747   @param timer
748     The timer parameter specifies the Timer block to configure.
749  */
750 static inline void
MSS_TIM64_disable_irq(TIMER_TypeDef * timer)751 MSS_TIM64_disable_irq(TIMER_TypeDef* timer)
752 {
753     timer->TIM64_CTRL &= ~((uint32_t)TIM64_INTEN_MASK);
754     PLIC_DisableIRQ(TIMER1_PLIC);
755 }
756 
757 /*-------------------------------------------------------------------------*//**
758   The MSS_TIM64_clear_irq() function is used to clear a pending interrupt from
759   the 64-bit timer. This function also clears the interrupt in the RISC-V PLIC.
760 
761   Note:You must call the MSS_TIM64_clear_irq() function as part of your
762        implementation of the Timer1_IRQHandler() 64-bit timer interrupt service
763        routine (ISR) in order to prevent the same interrupt event retriggering
764        a call to the ISR.
765 
766   @param timer
767     The timer parameter specifies the Timer block to configure.
768  */
769 static inline void
MSS_TIM64_clear_irq(TIMER_TypeDef * timer)770 MSS_TIM64_clear_irq(TIMER_TypeDef* timer)
771 {
772     timer->TIM64_RIS = 1u;
773 }
774 
775 #ifdef __cplusplus
776 }
777 #endif
778 
779 #endif /*MSS_TIMER_H_*/
780