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