1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017, 2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_lpit.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.lpit"
17 #endif
18 
19 #if defined(LPIT_RSTS)
20 #define LPIT_RESETS_ARRAY LPIT_RSTS
21 #endif
22 
23 /*******************************************************************************
24  * Variables
25  ******************************************************************************/
26 
27 /*! @brief Array to map LPIT instance number to base pointer. */
28 static LPIT_Type *const s_lpitBases[] = LPIT_BASE_PTRS;
29 
30 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
31 /*! @brief Clock array name */
32 static const clock_ip_name_t s_lpitClock[] = LPIT_CLOCKS;
33 
34 #if defined(LPIT_PERIPH_CLOCKS)
35 /* Array of LPIT functional clock name. */
36 static const clock_ip_name_t s_lpitPeriphClocks[] = LPIT_PERIPH_CLOCKS;
37 #endif
38 
39 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
40 
41 #if defined(LPIT_RESETS_ARRAY)
42 /* Reset array */
43 static const reset_ip_name_t s_lpitResets[] = LPIT_RESETS_ARRAY;
44 #endif
45 
46 /*******************************************************************************
47  * Prototypes
48  ******************************************************************************/
49 
50 /*!
51  * @brief Get the instance for LPIT module.
52  *
53  * @param base LPIT base address
54  */
55 uint32_t LPIT_GetInstance(LPIT_Type *base);
56 
57 /*******************************************************************************
58  * Code
59  ******************************************************************************/
60 
LPIT_GetInstance(LPIT_Type * base)61 uint32_t LPIT_GetInstance(LPIT_Type *base)
62 {
63     uint32_t instance;
64 
65     /* Find the instance index from base address mappings. */
66     /*
67      * $Branch Coverage Justification$
68      * (instance >= ARRAY_SIZE(s_lpitBases)) not covered. The peripheral base
69      * address is always valid and checked by assert.
70      */
71     for (instance = 0U; instance < ARRAY_SIZE(s_lpitBases); instance++)
72     {
73         /*
74          * $Branch Coverage Justification$
75          * (s_lpitBases[instance] != base) not covered. The peripheral base
76          * address is always valid and checked by assert.
77          */
78         if (s_lpitBases[instance] == base)
79         {
80             break;
81         }
82     }
83 
84     assert(instance < ARRAY_SIZE(s_lpitBases));
85 
86     return instance;
87 }
88 
89 /*!
90  * brief Ungates the LPIT clock and configures the peripheral for a basic operation.
91  *
92  * This function issues a software reset to reset all channels and registers except the Module
93  * Control register.
94  *
95  * note This API should be called at the beginning of the application using the LPIT driver.
96  *
97  * param base   LPIT peripheral base address.
98  * param config Pointer to the user configuration structure.
99  */
LPIT_Init(LPIT_Type * base,const lpit_config_t * config)100 void LPIT_Init(LPIT_Type *base, const lpit_config_t *config)
101 {
102     assert(NULL != config);
103 
104 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
105 
106     uint32_t instance = LPIT_GetInstance(base);
107 
108     /* Enable the clock */
109     (void)CLOCK_EnableClock(s_lpitClock[instance]);
110 #if defined(LPIT_PERIPH_CLOCKS)
111     CLOCK_EnableClock(s_lpitPeriphClocks[instance]);
112 #endif
113 
114 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
115 
116 #if defined(LPIT_RESETS_ARRAY)
117     RESET_ReleasePeripheralReset(s_lpitResets[LPIT_GetInstance(base)]);
118 #endif
119 
120     /* Reset the timer channels and registers except the MCR register */
121     LPIT_Reset(base);
122 
123     /* Setup timer operation in debug and doze modes and enable the module */
124     base->MCR =
125         (LPIT_MCR_DBG_EN(config->enableRunInDebug) | LPIT_MCR_DOZE_EN(config->enableRunInDoze) | LPIT_MCR_M_CEN_MASK);
126 }
127 
128 /*!
129  * brief Disables the module and gates the LPIT clock.
130  *
131  * param base LPIT peripheral base address.
132  */
LPIT_Deinit(LPIT_Type * base)133 void LPIT_Deinit(LPIT_Type *base)
134 {
135     /* Disable the module */
136     base->MCR &= ~LPIT_MCR_M_CEN_MASK;
137 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
138 
139     uint32_t instance = LPIT_GetInstance(base);
140 
141     /* Disable the clock */
142     (void)CLOCK_DisableClock(s_lpitClock[instance]);
143 #if defined(LPIT_PERIPH_CLOCKS)
144     CLOCK_DisableClock(s_lpitPeriphClocks[instance]);
145 #endif
146 
147 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
148 }
149 
150 /*!
151  * brief Fills in the LPIT configuration structure with default settings.
152  *
153  * The default values are:
154  * code
155  *    config->enableRunInDebug = false;
156  *    config->enableRunInDoze = false;
157  * endcode
158  * param config Pointer to the user configuration structure.
159  */
LPIT_GetDefaultConfig(lpit_config_t * config)160 void LPIT_GetDefaultConfig(lpit_config_t *config)
161 {
162     assert(NULL != config);
163 
164     /* Initializes the configure structure to zero. */
165     (void)memset(config, 0, sizeof(*config));
166 
167     /* Timers are stopped in debug mode */
168     config->enableRunInDebug = false;
169     /* Timers are stopped in doze mode */
170     config->enableRunInDoze = false;
171 }
172 
173 /*!
174  * brief Sets up an LPIT channel based on the user's preference.
175  *
176  * This function sets up the operation mode to one of the options available in the
177  * enumeration ::lpit_timer_modes_t. It sets the trigger source as either internal or external,
178  * trigger selection and the timers behaviour when a timeout occurs. It also chains
179  * the timer if a prior timer if requested by the user.
180  *
181  * param base      LPIT peripheral base address.
182  * param channel   Channel that is being configured.
183  * param chnlSetup Configuration parameters.
184  */
LPIT_SetupChannel(LPIT_Type * base,lpit_chnl_t channel,const lpit_chnl_params_t * chnlSetup)185 status_t LPIT_SetupChannel(LPIT_Type *base, lpit_chnl_t channel, const lpit_chnl_params_t *chnlSetup)
186 {
187     assert(NULL != chnlSetup);
188 
189     status_t status = kStatus_Success;
190 
191     /* Cannot assert the chain bit for channel 0 */
192     if ((channel == kLPIT_Chnl_0) && (chnlSetup->chainChannel == true))
193     {
194         status = kStatus_Fail;
195     }
196     else
197     {
198         uint32_t reg = 0U;
199 
200         /* Setup the channel counters operation mode, trigger operation, chain mode */
201         reg = (LPIT_TCTRL_MODE(chnlSetup->timerMode) | LPIT_TCTRL_TRG_SRC(chnlSetup->triggerSource) |
202                LPIT_TCTRL_TRG_SEL(chnlSetup->triggerSelect) | LPIT_TCTRL_TROT(chnlSetup->enableReloadOnTrigger) |
203                LPIT_TCTRL_TSOI(chnlSetup->enableStopOnTimeout) | LPIT_TCTRL_TSOT(chnlSetup->enableStartOnTrigger) |
204                LPIT_TCTRL_CHAIN(chnlSetup->chainChannel));
205 
206         base->CHANNEL[channel].TCTRL = reg;
207     }
208 
209     return status;
210 }
211