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