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