1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #ifndef _FSL_LPIT_H_
9 #define _FSL_LPIT_H_
10 
11 #include "fsl_common.h"
12 
13 /*!
14  * @addtogroup lpit
15  * @{
16  */
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 /*! @name Driver version */
23 /*@{*/
24 #define FSL_LPIT_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0 */
25                                                         /*@{*/
26 
27 /*!
28  * @brief List of LPIT channels
29  * @note Actual number of available channels is SoC-dependent
30  */
31 typedef enum _lpit_chnl
32 {
33     kLPIT_Chnl_0 = 0U, /*!< LPIT channel number 0*/
34     kLPIT_Chnl_1,      /*!< LPIT channel number 1 */
35     kLPIT_Chnl_2,      /*!< LPIT channel number 2 */
36     kLPIT_Chnl_3,      /*!< LPIT channel number 3 */
37 } lpit_chnl_t;
38 
39 /*! @brief Mode options available for the LPIT timer. */
40 typedef enum _lpit_timer_modes
41 {
42     kLPIT_PeriodicCounter = 0U, /*!< Use the all 32-bits, counter loads and decrements to zero */
43     kLPIT_DualPeriodicCounter,  /*!< Counter loads, lower 16-bits  decrement to zero, then
44                                      upper 16-bits  decrement */
45     kLPIT_TriggerAccumulator,   /*!< Counter loads on first trigger and decrements on each trigger */
46     kLPIT_InputCapture          /*!< Counter  loads with 0xFFFFFFFF, decrements to zero. It stores
47                                     the inverse of the current value when a input trigger is detected */
48 } lpit_timer_modes_t;
49 
50 /*!
51  * @brief Trigger options available.
52  *
53  * This is used for both internal and external trigger sources. The actual trigger options
54  * available is SoC-specific, user should refer to the reference manual.
55  */
56 typedef enum _lpit_trigger_select
57 {
58     kLPIT_Trigger_TimerChn0 = 0U, /*!< Channel 0 is selected as a trigger source */
59     kLPIT_Trigger_TimerChn1,      /*!< Channel 1 is selected as a trigger source */
60     kLPIT_Trigger_TimerChn2,      /*!< Channel 2 is selected as a trigger source */
61     kLPIT_Trigger_TimerChn3,      /*!< Channel 3 is selected as a trigger source */
62     kLPIT_Trigger_TimerChn4,      /*!< Channel 4 is selected as a trigger source */
63     kLPIT_Trigger_TimerChn5,      /*!< Channel 5 is selected as a trigger source */
64     kLPIT_Trigger_TimerChn6,      /*!< Channel 6 is selected as a trigger source */
65     kLPIT_Trigger_TimerChn7,      /*!< Channel 7 is selected as a trigger source */
66     kLPIT_Trigger_TimerChn8,      /*!< Channel 8 is selected as a trigger source */
67     kLPIT_Trigger_TimerChn9,      /*!< Channel 9 is selected as a trigger source */
68     kLPIT_Trigger_TimerChn10,     /*!< Channel 10 is selected as a trigger source */
69     kLPIT_Trigger_TimerChn11,     /*!< Channel 11 is selected as a trigger source */
70     kLPIT_Trigger_TimerChn12,     /*!< Channel 12 is selected as a trigger source */
71     kLPIT_Trigger_TimerChn13,     /*!< Channel 13 is selected as a trigger source */
72     kLPIT_Trigger_TimerChn14,     /*!< Channel 14 is selected as a trigger source */
73     kLPIT_Trigger_TimerChn15      /*!< Channel 15 is selected as a trigger source */
74 } lpit_trigger_select_t;
75 
76 /*! @brief Trigger source options available */
77 typedef enum _lpit_trigger_source
78 {
79     kLPIT_TriggerSource_External = 0U, /*!< Use external trigger input */
80     kLPIT_TriggerSource_Internal       /*!< Use internal trigger */
81 } lpit_trigger_source_t;
82 
83 /*!
84  * @brief List of LPIT interrupts.
85  *
86  * @note Number of timer channels are SoC-specific. See the SoC Reference Manual.
87  */
88 typedef enum _lpit_interrupt_enable
89 {
90     kLPIT_Channel0TimerInterruptEnable = (1U << 0), /*!< Channel 0 Timer interrupt */
91     kLPIT_Channel1TimerInterruptEnable = (1U << 1), /*!< Channel 1 Timer interrupt */
92     kLPIT_Channel2TimerInterruptEnable = (1U << 2), /*!< Channel 2 Timer interrupt */
93     kLPIT_Channel3TimerInterruptEnable = (1U << 3), /*!< Channel 3 Timer interrupt */
94 } lpit_interrupt_enable_t;
95 
96 /*!
97  * @brief List of LPIT status flags
98  *
99  * @note Number of timer channels are SoC-specific. See the SoC Reference Manual.
100  */
101 typedef enum _lpit_status_flags
102 {
103     kLPIT_Channel0TimerFlag = (1U << 0), /*!< Channel 0 Timer interrupt flag */
104     kLPIT_Channel1TimerFlag = (1U << 1), /*!< Channel 1 Timer interrupt flag */
105     kLPIT_Channel2TimerFlag = (1U << 2), /*!< Channel 2 Timer interrupt flag */
106     kLPIT_Channel3TimerFlag = (1U << 3), /*!< Channel 3 Timer interrupt flag */
107 } lpit_status_flags_t;
108 
109 /*! @brief Structure to configure the channel timer. */
110 typedef struct _lpit_chnl_params
111 {
112     bool chainChannel;                   /*!< true: Timer chained to previous timer;
113                                               false: Timer not chained */
114     lpit_timer_modes_t timerMode;        /*!< Timers mode of operation. */
115     lpit_trigger_select_t triggerSelect; /*!< Trigger selection for the timer */
116     lpit_trigger_source_t triggerSource; /*!< Decides if we use external or internal trigger. */
117     bool enableReloadOnTrigger;          /*!< true: Timer reloads when a trigger is detected;
118                                               false: No effect */
119     bool enableStopOnTimeout;            /*!< true: Timer will stop after timeout;
120                                               false: does not stop after timeout */
121     bool enableStartOnTrigger;           /*!< true: Timer starts when a trigger is detected;
122                                               false: decrement immediately */
123 } lpit_chnl_params_t;
124 
125 /*!
126  * @brief LPIT configuration structure
127  *
128  * This structure holds the configuration settings for the LPIT peripheral. To initialize this
129  * structure to reasonable defaults, call the LPIT_GetDefaultConfig() function and pass a
130  * pointer to the configuration structure instance.
131  *
132  * The configuration structure can be made constant so as to reside in flash.
133  */
134 typedef struct _lpit_config
135 {
136     bool enableRunInDebug; /*!< true: Timers run in debug mode; false: Timers stop in debug mode */
137     bool enableRunInDoze;  /*!< true: Timers run in doze mode; false: Timers stop in doze mode */
138 } lpit_config_t;
139 
140 /*******************************************************************************
141  * API
142  ******************************************************************************/
143 
144 #if defined(__cplusplus)
145 extern "C" {
146 #endif
147 
148 /*!
149  * @name Initialization and deinitialization
150  * @{
151  */
152 
153 /*!
154  * @brief Ungates the LPIT clock and configures the peripheral for a basic operation.
155  *
156  * This function issues a software reset to reset all channels and registers except the Module
157  * Control register.
158  *
159  * @note This API should be called at the beginning of the application using the LPIT driver.
160  *
161  * @param base   LPIT peripheral base address.
162  * @param config Pointer to the user configuration structure.
163  */
164 void LPIT_Init(LPIT_Type *base, const lpit_config_t *config);
165 
166 /*!
167  * @brief Disables the module and gates the LPIT clock.
168  *
169  * @param base LPIT peripheral base address.
170  */
171 void LPIT_Deinit(LPIT_Type *base);
172 
173 /*!
174  * @brief Fills in the LPIT configuration structure with default settings.
175  *
176  * The default values are:
177  * @code
178  *    config->enableRunInDebug = false;
179  *    config->enableRunInDoze = false;
180  * @endcode
181  * @param config Pointer to the user configuration structure.
182  */
183 void LPIT_GetDefaultConfig(lpit_config_t *config);
184 
185 /*!
186  * @brief Sets up an LPIT channel based on the user's preference.
187  *
188  * This function sets up the operation mode to one of the options available in the
189  * enumeration ::lpit_timer_modes_t. It sets the trigger source as either internal or external,
190  * trigger selection and the timers behaviour when a timeout occurs. It also chains
191  * the timer if a prior timer if requested by the user.
192  *
193  * @param base      LPIT peripheral base address.
194  * @param channel   Channel that is being configured.
195  * @param chnlSetup Configuration parameters.
196  */
197 status_t LPIT_SetupChannel(LPIT_Type *base, lpit_chnl_t channel, const lpit_chnl_params_t *chnlSetup);
198 
199 /*! @}*/
200 
201 /*!
202  * @name Interrupt Interface
203  * @{
204  */
205 
206 /*!
207  * @brief Enables the selected PIT interrupts.
208  *
209  * @param base LPIT peripheral base address.
210  * @param mask The interrupts to enable. This is a logical OR of members of the
211  *             enumeration ::lpit_interrupt_enable_t
212  */
LPIT_EnableInterrupts(LPIT_Type * base,uint32_t mask)213 static inline void LPIT_EnableInterrupts(LPIT_Type *base, uint32_t mask)
214 {
215     base->MIER |= mask;
216 }
217 
218 /*!
219  * @brief Disables the selected PIT interrupts.
220  *
221  * @param base LPIT peripheral base address.
222  * @param mask The interrupts to enable. This is a logical OR of members of the
223  *             enumeration ::lpit_interrupt_enable_t
224  */
LPIT_DisableInterrupts(LPIT_Type * base,uint32_t mask)225 static inline void LPIT_DisableInterrupts(LPIT_Type *base, uint32_t mask)
226 {
227     base->MIER &= ~mask;
228 }
229 
230 /*!
231  * @brief Gets the enabled LPIT interrupts.
232  *
233  * @param base LPIT peripheral base address.
234  *
235  * @return The enabled interrupts. This is the logical OR of members of the
236  *         enumeration ::lpit_interrupt_enable_t
237  */
LPIT_GetEnabledInterrupts(LPIT_Type * base)238 static inline uint32_t LPIT_GetEnabledInterrupts(LPIT_Type *base)
239 {
240     return base->MIER;
241 }
242 
243 /*! @}*/
244 
245 /*!
246  * @name Status Interface
247  * @{
248  */
249 
250 /*!
251  * @brief Gets the LPIT status flags.
252  *
253  * @param base LPIT peripheral base address.
254  *
255  * @return The status flags. This is the logical OR of members of the
256  *         enumeration ::lpit_status_flags_t
257  */
LPIT_GetStatusFlags(LPIT_Type * base)258 static inline uint32_t LPIT_GetStatusFlags(LPIT_Type *base)
259 {
260     return base->MSR;
261 }
262 
263 /*!
264  * @brief Clears the LPIT status flags.
265  *
266  * @param base LPIT peripheral base address.
267  * @param mask The status flags to clear. This is a logical OR of members of the
268  *             enumeration ::lpit_status_flags_t
269  */
LPIT_ClearStatusFlags(LPIT_Type * base,uint32_t mask)270 static inline void LPIT_ClearStatusFlags(LPIT_Type *base, uint32_t mask)
271 {
272     /* Writing a 1 to the status bit will clear the flag */
273     base->MSR = mask;
274 }
275 
276 /*! @}*/
277 
278 /*!
279  * @name Read and Write the timer period
280  * @{
281  */
282 
283 /*!
284  * @brief Sets the timer period in units of count.
285  *
286  * Timers begin counting down from the value set by this function until it reaches 0, at which point
287  * it generates an interrupt and loads this register value again.
288  * Writing a new value to this register does not restart the timer. Instead, the value
289  * is loaded after the timer expires.
290  *
291  * @note User can call the utility macros provided in fsl_common.h to convert to ticks.
292  *
293  * @param base    LPIT peripheral base address.
294  * @param channel Timer channel number.
295  * @param ticks   Timer period in units of ticks.
296  */
LPIT_SetTimerPeriod(LPIT_Type * base,lpit_chnl_t channel,uint32_t ticks)297 static inline void LPIT_SetTimerPeriod(LPIT_Type *base, lpit_chnl_t channel, uint32_t ticks)
298 {
299     assert(ticks > 2U);
300     base->CHANNEL[channel].TVAL = ticks - 1U;
301 }
302 
303 /*!
304  * @brief Sets the timer period in units of count.
305  *
306  * In the Dual 16-bit Periodic Counter mode, the counter will load and then the lower
307  * 16-bits will decrement down to zero, which will assert the output pre-trigger. The
308  * upper 16-bits will then decrement down to zero, which will negate the output pre-trigger
309  * and set the timer interrupt flag.
310  *
311  * @note Set TVAL register to 0 or 1 is invalid in compare mode.
312  *
313  * @param base    LPIT peripheral base address.
314  * @param channel Timer channel number.
315  * @param ticks   Timer period in units of ticks.
316  */
LPIT_SetTimerValue(LPIT_Type * base,lpit_chnl_t channel,uint32_t ticks)317 static inline void LPIT_SetTimerValue(LPIT_Type *base, lpit_chnl_t channel, uint32_t ticks)
318 {
319     assert(ticks > 1U);
320     base->CHANNEL[channel].TVAL = ticks;
321 }
322 
323 /*!
324  * @brief Reads the current timer counting value.
325  *
326  * This function returns the real-time timer counting value, in a range from 0 to a
327  * timer period.
328  *
329  * @note User can call the utility macros provided in fsl_common.h to convert ticks to microseconds or milliseconds.
330  *
331  * @param base    LPIT peripheral base address.
332  * @param channel Timer channel number.
333  *
334  * @return Current timer counting value in ticks.
335  */
LPIT_GetCurrentTimerCount(LPIT_Type * base,lpit_chnl_t channel)336 static inline uint32_t LPIT_GetCurrentTimerCount(LPIT_Type *base, lpit_chnl_t channel)
337 {
338     return base->CHANNEL[channel].CVAL;
339 }
340 
341 /*! @}*/
342 
343 /*!
344  * @name Timer Start and Stop
345  * @{
346  */
347 
348 /*!
349  * @brief Starts the timer counting.
350  *
351  * After calling this function, timers load the period value and count down to 0. When the timer
352  * reaches 0, it generates a trigger pulse and sets the timeout interrupt flag.
353  *
354  * @param base    LPIT peripheral base address.
355  * @param channel Timer channel number.
356  */
LPIT_StartTimer(LPIT_Type * base,lpit_chnl_t channel)357 static inline void LPIT_StartTimer(LPIT_Type *base, lpit_chnl_t channel)
358 {
359     uint32_t shift = LPIT_SETTEN_SET_T_EN_0_MASK;
360 
361     base->SETTEN |= shift << ((uint32_t)channel);
362 }
363 /*!
364  * @brief Stops the timer counting.
365  *
366  * @param base    LPIT peripheral base address.
367  * @param channel Timer channel number.
368  */
LPIT_StopTimer(LPIT_Type * base,lpit_chnl_t channel)369 static inline void LPIT_StopTimer(LPIT_Type *base, lpit_chnl_t channel)
370 {
371     uint32_t shift = LPIT_CLRTEN_CLR_T_EN_0_MASK;
372 
373     base->CLRTEN |= shift << ((uint32_t)channel);
374 }
375 
376 /*! @}*/
377 
378 /*!
379  * @brief Performs a software reset on the LPIT module.
380  *
381  * This resets all channels and registers except the Module Control Register.
382  *
383  * @param base LPIT peripheral base address.
384  */
LPIT_Reset(LPIT_Type * base)385 static inline void LPIT_Reset(LPIT_Type *base)
386 {
387     base->MCR |= LPIT_MCR_SW_RST_MASK;
388     base->MCR &= ~LPIT_MCR_SW_RST_MASK;
389 }
390 
391 #if defined(__cplusplus)
392 }
393 #endif
394 
395 /*! @}*/
396 
397 #endif /* __FSL_LPIT_H__ */
398