1 /*
2  * Copyright 2019-2024 NXP.
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_wuu.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.wuu"
17 #endif
18 
19 #define WUU_PE_REG_BIT_FIELD_MASK  0x03UL
20 #define WUU_PDC_REG_BIT_FIELD_MASK 0x03UL
21 #define WUU_PMC_REG_BIT_FIELD_MASK 0x01UL
22 
23 #define WUU_ME_REG_WUME_FIELD_MASK 0x01UL
24 #define WUU_DE_REG_WUME_FIELD_MASK 0x01UL
25 
26 #define WUU_FILT_REG_FILTE_FIELD_MASK   0x60U
27 #define WUU_FILT_REG_FILTSET_FIELD_MASK 0x1FU
28 #define WUU_FDC_REG_FILTC_FIELD_MASK    0x3U
29 #define WUU_FMC_REG_FILTM_FIELD_MASK    0x1U
30 
31 #define WUU_FILT_REG_FILTSET_FIELD(x)            (((uint32_t)(x) << 5UL) & WUU_FILT_REG_FILTE_FIELD_MASK)
32 #define WUU_CLEAR_BIT_FIELD_IN_REG(mask, offset) (~((uint32_t)(mask) << (offset)))
33 #define WUU_SET_BIT_FIELD_IN_REG(val, offset)    ((uint32_t)(val) << (offset))
34 /*******************************************************************************
35  * Prototypes
36  ******************************************************************************/
37 
38 /*******************************************************************************
39  * Variables
40  ******************************************************************************/
41 
42 /*******************************************************************************
43  * Code
44  ******************************************************************************/
45 
46 /*!
47  * brief Enables and Configs External WakeUp Pins.
48  *
49  * This function enables/disables the external pin as wakeup input. What's more this
50  * function configs pins options, including edge detection wakeup event and operate mode.
51  *
52  * param base     MUU peripheral base address.
53  * param pinIndex The index of the external input pin. See Reference Manual for the details.
54  * param config   Pointer to wuu_external_wakeup_pin_config_t structure.
55  */
WUU_SetExternalWakeUpPinsConfig(WUU_Type * base,uint8_t pinIndex,const wuu_external_wakeup_pin_config_t * config)56 void WUU_SetExternalWakeUpPinsConfig(WUU_Type *base, uint8_t pinIndex, const wuu_external_wakeup_pin_config_t *config)
57 {
58     assert(config != NULL);
59 
60     volatile uint32_t *edgeRegBase  = NULL;
61     volatile uint32_t *eventRegBase = NULL;
62     uint32_t edgeReg;
63     uint32_t eventReg;
64     uint32_t modeReg;
65     uint8_t offset;
66 
67     /* Calculate offset. */
68     offset = 2U * (pinIndex & 0xFU);
69 
70     if (config->edge != kWUU_ExternalPinDisable)
71     {
72         /* Based on pin index, get register base address. */
73         if ((pinIndex >> 4U) != 0U)
74         {
75             edgeRegBase  = &base->PE2;
76             eventRegBase = &base->PDC2;
77         }
78         else
79         {
80             edgeRegBase  = &base->PE1;
81             eventRegBase = &base->PDC1;
82         }
83 
84         /* Enable and config the edge detection. */
85         edgeReg = *edgeRegBase;
86         edgeReg &= WUU_CLEAR_BIT_FIELD_IN_REG(WUU_PE_REG_BIT_FIELD_MASK, offset);
87         edgeReg |= WUU_SET_BIT_FIELD_IN_REG(config->edge, offset);
88         *edgeRegBase = edgeReg;
89 
90         /* Config the wakeup event. */
91         eventReg = *eventRegBase;
92         eventReg &= WUU_CLEAR_BIT_FIELD_IN_REG(WUU_PDC_REG_BIT_FIELD_MASK, offset);
93         eventReg |= WUU_SET_BIT_FIELD_IN_REG(config->event, offset);
94         *eventRegBase = eventReg;
95 
96         /* Config operate mode. */
97         modeReg = base->PMC;
98         modeReg &= WUU_CLEAR_BIT_FIELD_IN_REG(WUU_PMC_REG_BIT_FIELD_MASK, pinIndex);
99         modeReg |= WUU_SET_BIT_FIELD_IN_REG(config->mode, pinIndex);
100 
101         base->PMC = modeReg;
102     }
103     else
104     {
105         /* Based on pin index, get register base address. */
106         if ((pinIndex >> 4U) != 0U)
107         {
108             edgeRegBase = &base->PE2;
109         }
110         else
111         {
112             edgeRegBase = &base->PE1;
113         }
114 
115         edgeReg = *edgeRegBase;
116         edgeReg &= WUU_CLEAR_BIT_FIELD_IN_REG(WUU_PE_REG_BIT_FIELD_MASK, offset);
117         *edgeRegBase = edgeReg;
118     }
119 }
120 
121 /*!
122  * brief Disable and clear external wakeup pin settings.
123  *
124  * param base MUU peripheral base address.
125  * param pinIndex The index of the external input pin.
126  */
WUU_ClearExternalWakeupPinsConfig(WUU_Type * base,uint8_t pinIndex)127 void WUU_ClearExternalWakeupPinsConfig(WUU_Type *base, uint8_t pinIndex)
128 {
129     if (pinIndex <= 15U)
130     {
131         base->PE1 &= ~(WUU_PE_REG_BIT_FIELD_MASK << (2UL * (uint32_t)pinIndex));
132         base->PDC1 &= ~(WUU_PDC_REG_BIT_FIELD_MASK << (2UL * (uint32_t)pinIndex));
133     }
134     else
135     {
136         base->PE1 &= ~(WUU_PE_REG_BIT_FIELD_MASK << (2UL * (uint32_t)((uint32_t)pinIndex % 16UL)));
137         base->PDC1 &= ~(WUU_PDC_REG_BIT_FIELD_MASK << (2UL * (uint32_t)((uint32_t)pinIndex % 16UL)));
138     }
139 }
140 
141 /*!
142  * brief Config Internal modules' event as the wake up soures.
143  *
144  * This function configs the internal modules event as the wake up sources.
145  *
146  * param base WUU peripheral base address.
147  * param moduleIndex The selected internal module. See the Reference Manual for the details.
148  * param event Select interrupt or DMA/Trigger of the internal module as the wake up source.
149  */
WUU_SetInternalWakeUpModulesConfig(WUU_Type * base,uint8_t moduleIndex,wuu_internal_wakeup_module_event_t event)150 void WUU_SetInternalWakeUpModulesConfig(WUU_Type *base, uint8_t moduleIndex, wuu_internal_wakeup_module_event_t event)
151 {
152     switch (event)
153     {
154         case kWUU_InternalModuleInterrupt:
155             base->ME |= WUU_SET_BIT_FIELD_IN_REG(WUU_ME_REG_WUME_FIELD_MASK, moduleIndex);
156             break;
157         case kWUU_InternalModuleDMATrigger:
158             base->DE |= WUU_SET_BIT_FIELD_IN_REG(WUU_DE_REG_WUME_FIELD_MASK, moduleIndex);
159             break;
160         default:
161             assert(false);
162             break;
163     }
164 }
165 
166 /*!
167  * brief Disable an on-chip internal modules' event as the wakeup sources.
168  *
169  * param base WUU peripheral base address.
170  * param moduleIndex The selected internal module. See the Reference Manual for the details.
171  * param event The event(interrupt or DMA/trigger) of the internal module to disable.
172  */
WUU_ClearInternalWakeUpModulesConfig(WUU_Type * base,uint8_t moduleIndex,wuu_internal_wakeup_module_event_t event)173 void WUU_ClearInternalWakeUpModulesConfig(WUU_Type *base, uint8_t moduleIndex, wuu_internal_wakeup_module_event_t event)
174 {
175     switch(event)
176     {
177         case kWUU_InternalModuleInterrupt:
178             base->ME &= ~WUU_SET_BIT_FIELD_IN_REG(WUU_ME_REG_WUME_FIELD_MASK, moduleIndex);
179             break;
180         case kWUU_InternalModuleDMATrigger:
181             base->DE &= ~WUU_SET_BIT_FIELD_IN_REG(WUU_DE_REG_WUME_FIELD_MASK, moduleIndex);
182             break;
183         default:
184             assert(false);
185             break;
186     }
187 }
188 
189 /*!
190  * brief Configs and Enables Pin filters.
191  *
192  * This function configs Pin filter, including pin select, filer operate mode
193  * filer wakeup event and filter edge detection.
194  *
195  * param base WUU peripheral base address.
196  * param filterIndex The index of the pin filer.
197  * param config Pointer to wuu_pin_filter_config_t structure.
198  */
WUU_SetPinFilterConfig(WUU_Type * base,uint8_t filterIndex,const wuu_pin_filter_config_t * config)199 void WUU_SetPinFilterConfig(WUU_Type *base, uint8_t filterIndex, const wuu_pin_filter_config_t *config)
200 {
201     assert(config != NULL);
202 
203     uint8_t shift;
204     uint32_t filterReg;
205     uint32_t eventReg;
206     uint32_t modeReg;
207 
208     shift     = (filterIndex - 1U) * 8U;
209     filterReg = base->FILT;
210     filterReg &= WUU_CLEAR_BIT_FIELD_IN_REG(WUU_FILT_REG_FILTE_FIELD_MASK, shift);
211     filterReg |= WUU_SET_BIT_FIELD_IN_REG(WUU_FILT_REG_FILTSET_FIELD(config->edge), shift);
212 
213     if (config->edge != kWUU_FilterDisabled)
214     {
215         filterReg &= WUU_CLEAR_BIT_FIELD_IN_REG(WUU_FILT_REG_FILTSET_FIELD_MASK, shift);
216         filterReg |= WUU_SET_BIT_FIELD_IN_REG(config->pinIndex, shift);
217 
218         /* Config wake up event. */
219         shift    = (filterIndex - 1U) * 2U;
220         eventReg = base->FDC;
221         eventReg &= WUU_CLEAR_BIT_FIELD_IN_REG(WUU_FDC_REG_FILTC_FIELD_MASK, shift);
222         eventReg |= WUU_SET_BIT_FIELD_IN_REG(config->event, shift);
223         base->FDC = eventReg;
224 
225         /* Config operate mode. */
226         shift   = (filterIndex - 1U) * 1U;
227         modeReg = base->FMC;
228         modeReg &= WUU_CLEAR_BIT_FIELD_IN_REG(WUU_FMC_REG_FILTM_FIELD_MASK, shift);
229         modeReg |= WUU_SET_BIT_FIELD_IN_REG(config->mode, shift);
230         base->FMC = modeReg;
231     }
232 
233     base->FILT = filterReg;
234 }
235 
236 /*!
237  * brief Gets the pin filter configuration.
238  *
239  * This function gets the pin filter flag.
240  *
241  * param base WUU peripheral base address.
242  * param filterIndex A pin filter index, which starts from 1.
243  * return True if the flag is a source of the existing low-leakage power mode.
244  */
WUU_GetPinFilterFlag(WUU_Type * base,uint8_t filterIndex)245 bool WUU_GetPinFilterFlag(WUU_Type *base, uint8_t filterIndex)
246 {
247     bool ret = false;
248 
249     switch (filterIndex)
250     {
251         case 1:
252             ret = ((base->FILT & WUU_FILT_FILTF1_MASK) != 0U);
253             break;
254         case 2:
255             ret = ((base->FILT & WUU_FILT_FILTF2_MASK) != 0U);
256             break;
257         default:
258             ret = false;
259             break;
260     }
261 
262     return ret;
263 }
264 
265 /*!
266  * brief Clears the pin filter configuration.
267  *
268  * This function clears the pin filter flag.
269  *
270  * param base WUU peripheral base address.
271  * param filterIndex A pin filter index to clear the flag, starting from 1.
272  */
WUU_ClearPinFilterFlag(WUU_Type * base,uint8_t filterIndex)273 void WUU_ClearPinFilterFlag(WUU_Type *base, uint8_t filterIndex)
274 {
275     uint32_t reg;
276 
277     reg = base->FILT;
278     /* Clean the W1C bits, in case the flags are cleared by mistake. */
279     reg &= ~(WUU_FILT_FILTF1_MASK | WUU_FILT_FILTF2_MASK);
280 
281     reg |= WUU_SET_BIT_FIELD_IN_REG(WUU_FILT_FILTF1_MASK, ((filterIndex - 1U) * 8U));
282 
283     base->FILT = reg;
284 }
285 
286 /*!
287  * brief Gets the external wakeup source flag.
288  *
289  * This function checks the external pin flag to detect whether the MCU is
290  * woken up by the specific pin.
291  *
292  * param base WUU peripheral base address.
293  * param pinIndex     A pin index, which starts from 0.
294  * return True if the specific pin is a wakeup source.
295  */
WUU_GetExternalWakeupPinFlag(WUU_Type * base,uint32_t pinIndex)296 bool WUU_GetExternalWakeupPinFlag(WUU_Type *base, uint32_t pinIndex)
297 {
298     return (0U != (base->PF & (1UL << pinIndex)));
299 }
300 
301 /*!
302  * brief Clears the external wakeup source flag.
303  *
304  * This function clears the external wakeup source flag for a specific pin.
305  *
306  * param base WUU peripheral base address.
307  * param pinIndex A pin index, which starts from 0.
308  */
WUU_ClearExternalWakeupPinFlag(WUU_Type * base,uint32_t pinIndex)309 void WUU_ClearExternalWakeupPinFlag(WUU_Type *base, uint32_t pinIndex)
310 {
311     base->PF = (1UL << pinIndex);
312 }
313