1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_llwu.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.llwu"
14 #endif
15 
16 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN)
17 /*!
18  * brief Sets the external input pin source mode.
19  *
20  * This function sets the external input pin source mode that is used
21  * as a wake up source.
22  *
23  * param base LLWU peripheral base address.
24  * param pinIndex A pin index to be enabled as an external wakeup source starting from 1.
25  * param pinMode A pin configuration mode defined in the llwu_external_pin_modes_t.
26  */
LLWU_SetExternalWakeupPinMode(LLWU_Type * base,uint32_t pinIndex,llwu_external_pin_mode_t pinMode)27 void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_external_pin_mode_t pinMode)
28 {
29 #if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
30     volatile uint32_t *regBase;
31     uint32_t regOffset;
32     uint32_t reg;
33 
34     switch (pinIndex >> 4U)
35     {
36         case 0U:
37             regBase = &base->PE1;
38             break;
39 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
40         case 1U:
41             regBase = &base->PE2;
42             break;
43 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
44         default:
45             regBase = NULL;
46             break;
47     }
48 
49     if (NULL != regBase)
50     {
51         reg       = *regBase;
52         regOffset = ((pinIndex & 0x0FU) << 1U);
53         reg &= LLWU_REG_VAL(~(3UL << regOffset));
54         reg |= ((uint32_t)pinMode << regOffset);
55         *regBase = reg;
56     }
57 #else
58     volatile uint8_t *regBase;
59     uint8_t regOffset;
60     uint8_t reg;
61     switch (pinIndex >> 2U)
62     {
63         case 0U:
64             regBase = &base->PE1;
65             break;
66         case 1U:
67             regBase = &base->PE2;
68             break;
69 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
70         case 2U:
71             regBase = &base->PE3;
72             break;
73 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
74 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 12))
75         case 3U:
76             regBase = &base->PE4;
77             break;
78 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
79 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
80         case 4U:
81             regBase = &base->PE5;
82             break;
83 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
84 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 20))
85         case 5U:
86             regBase = &base->PE6;
87             break;
88 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
89 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
90         case 6U:
91             regBase = &base->PE7;
92             break;
93 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
94 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 28))
95         case 7U:
96             regBase = &base->PE8;
97             break;
98 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
99         default:
100             regBase = NULL;
101             break;
102     }
103 
104     if (NULL != regBase)
105     {
106         reg       = *regBase;
107         regOffset = (uint8_t)((pinIndex & 0x03U) << 1U);
108         reg &= LLWU_REG_VAL(~(3UL << regOffset));
109         reg |= (uint8_t)((uint32_t)pinMode << regOffset);
110         *regBase = reg;
111     }
112 #endif /* FSL_FEATURE_LLWU_REG_BITWIDTH == 32 */
113 }
114 
115 /*!
116  * brief Gets the external wakeup source flag.
117  *
118  * This function checks the external pin flag to detect whether the MCU is
119  * woken up by the specific pin.
120  *
121  * param base LLWU peripheral base address.
122  * param pinIndex     A pin index, which starts from 1.
123  * return True if the specific pin is a wakeup source.
124  */
LLWU_GetExternalWakeupPinFlag(LLWU_Type * base,uint32_t pinIndex)125 bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex)
126 {
127 #if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
128     return (0U != (base->PF & (1UL << pinIndex)));
129 #else
130     bool ret;
131     volatile uint8_t *regBase;
132 
133     switch (pinIndex >> 3U)
134     {
135 #if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF)
136         case 0U:
137             regBase = &base->PF1;
138             break;
139 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
140         case 1U:
141             regBase = &base->PF2;
142             break;
143 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
144 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
145         case 2U:
146             regBase = &base->PF3;
147             break;
148 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
149 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
150         case 3U:
151             regBase = &base->PF4;
152             break;
153 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
154 #else
155         case 0U:
156             regBase = &base->F1;
157             break;
158 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
159         case 1U:
160             regBase = &base->F2;
161             break;
162 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
163 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
164         case 2U:
165             regBase = &base->F3;
166             break;
167 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
168 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
169         case 3U:
170             regBase = &base->F4;
171             break;
172 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
173 #endif /* FSL_FEATURE_LLWU_HAS_PF */
174         default:
175             regBase = NULL;
176             break;
177     }
178 
179     if (NULL != regBase)
180     {
181         if (0U != (*regBase & (1U << pinIndex % 8U)))
182         {
183             ret = true;
184         }
185         else
186         {
187             ret = false;
188         }
189     }
190     else
191     {
192         ret = false;
193     }
194 
195     return ret;
196 #endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
197 }
198 
199 /*!
200  * brief Clears the external wakeup source flag.
201  *
202  * This function clears the external wakeup source flag for a specific pin.
203  *
204  * param base LLWU peripheral base address.
205  * param pinIndex A pin index, which starts from 1.
206  */
LLWU_ClearExternalWakeupPinFlag(LLWU_Type * base,uint32_t pinIndex)207 void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex)
208 {
209 #if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
210     base->PF = (1UL << pinIndex);
211 #else
212     volatile uint8_t *regBase;
213     switch (pinIndex >> 3U)
214     {
215 #if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF)
216         case 0U:
217             regBase = &base->PF1;
218             break;
219 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
220         case 1U:
221             regBase = &base->PF2;
222             break;
223 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
224 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
225         case 2U:
226             regBase = &base->PF3;
227             break;
228 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
229 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
230         case 3U:
231             regBase = &base->PF4;
232             break;
233 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
234 #else
235         case 0U:
236             regBase = &base->F1;
237             break;
238 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
239         case 1U:
240             regBase = &base->F2;
241             break;
242 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
243 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
244         case 2U:
245             regBase = &base->F3;
246             break;
247 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
248 #if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
249         case 3U:
250             regBase = &base->F4;
251             break;
252 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
253 #endif /* FSL_FEATURE_LLWU_HAS_PF */
254         default:
255             regBase = NULL;
256             break;
257     }
258     if (NULL != regBase)
259     {
260         *regBase = (1U << pinIndex % 8U);
261     }
262 #endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
263 }
264 #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
265 
266 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER)
267 /*!
268  * brief Sets the pin filter configuration.
269  *
270  * This function sets the pin filter configuration.
271  *
272  * param base LLWU peripheral base address.
273  * param filterIndex A pin filter index used to enable/disable the digital filter, starting from 1.
274  * param filterMode A filter mode configuration
275  */
LLWU_SetPinFilterMode(LLWU_Type * base,uint32_t filterIndex,llwu_external_pin_filter_mode_t filterMode)276 void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_pin_filter_mode_t filterMode)
277 {
278 #if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
279     uint32_t filt;
280     uint32_t shiftInReg;
281 
282     if ((filterIndex > 0U) && (filterIndex <= (uint32_t)FSL_FEATURE_LLWU_HAS_PIN_FILTER))
283     {
284         shiftInReg = (filterIndex - 1U) * 8U;
285 
286         filt = base->FILT;
287         /* Clean the W1C bits, in case the flags are cleared by mistake. */
288         filt &= ~(((uint32_t)LLWU_FILT_FILTF1_MASK << 0U) | ((uint32_t)LLWU_FILT_FILTF1_MASK << 8U) |
289                   ((uint32_t)LLWU_FILT_FILTF1_MASK << 16U) | ((uint32_t)LLWU_FILT_FILTF1_MASK << 24U));
290 
291         filt &= ~(((uint32_t)LLWU_FILT_FILTSEL1_MASK | (uint32_t)LLWU_FILT_FILTE1_MASK) << shiftInReg);
292 
293         filt |=
294             ((LLWU_FILT_FILTSEL1(filterMode.pinIndex) | LLWU_FILT_FILTE1(filterMode.filterMode) | LLWU_FILT_FILTF1_MASK)
295              << shiftInReg);
296 
297         base->FILT = filt;
298     }
299 #else
300     volatile uint8_t *regBase;
301 
302     switch (filterIndex)
303     {
304         case 1U:
305             regBase = &base->FILT1;
306             break;
307 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
308         case 2U:
309             regBase = &base->FILT2;
310             break;
311 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
312 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
313         case 3U:
314             regBase = &base->FILT3;
315             break;
316 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
317 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
318         case 4U:
319             regBase = &base->FILT4;
320             break;
321 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
322         default:
323             regBase = NULL;
324             break;
325     }
326 
327     if (NULL != regBase)
328     {
329         *regBase = (uint8_t)((*regBase & ~(LLWU_FILT1_FILTSEL_MASK | LLWU_FILT1_FILTE_MASK)) |
330                              LLWU_FILT1_FILTSEL(filterMode.pinIndex) | LLWU_FILT1_FILTE(filterMode.filterMode) |
331                              LLWU_FILT1_FILTF_MASK) /* W1C to clear the FILTF flag bit. */
332             ;
333     }
334 #endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
335 }
336 
337 /*!
338  * brief Gets the pin filter configuration.
339  *
340  * This function gets the pin filter flag.
341  *
342  * param base LLWU peripheral base address.
343  * param filterIndex A pin filter index, which starts from 1.
344  * return True if the flag is a source of the existing low-leakage power mode.
345  */
LLWU_GetPinFilterFlag(LLWU_Type * base,uint32_t filterIndex)346 bool LLWU_GetPinFilterFlag(LLWU_Type *base, uint32_t filterIndex)
347 {
348 #if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
349     return (0U != (base->FILT & (1UL << (filterIndex * 8U - 1U))));
350 #else
351     bool status = false;
352 
353     switch (filterIndex)
354     {
355         case 1:
356             status = ((base->FILT1 & LLWU_FILT1_FILTF_MASK) != 0U);
357             break;
358 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
359         case 2:
360             status = ((base->FILT2 & LLWU_FILT2_FILTF_MASK) != 0U);
361             break;
362 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
363 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
364         case 3:
365             status = ((base->FILT3 & LLWU_FILT3_FILTF_MASK) != 0U);
366             break;
367 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
368 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
369         case 4:
370             status = ((base->FILT4 & LLWU_FILT4_FILTF_MASK) != 0U);
371             break;
372 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
373         default:
374             status = false;
375             break;
376     }
377 
378     return status;
379 #endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
380 }
381 
382 /*!
383  * brief Clears the pin filter configuration.
384  *
385  * This function clears the pin filter flag.
386  *
387  * param base LLWU peripheral base address.
388  * param filterIndex A pin filter index to clear the flag, starting from 1.
389  */
LLWU_ClearPinFilterFlag(LLWU_Type * base,uint32_t filterIndex)390 void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex)
391 {
392 #if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
393 
394 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 0))
395     uint32_t reg;
396 
397     if ((filterIndex > 0U) && (filterIndex <= (uint32_t)FSL_FEATURE_LLWU_HAS_PIN_FILTER))
398     {
399         reg = base->FILT;
400 
401         /* Clean the W1C bits, in case the flags are cleared by mistake. */
402         reg &= ~(((uint32_t)LLWU_FILT_FILTF1_MASK << 0U) | ((uint32_t)LLWU_FILT_FILTF1_MASK << 8U) |
403                  ((uint32_t)LLWU_FILT_FILTF1_MASK << 16U) | ((uint32_t)LLWU_FILT_FILTF1_MASK << 24U));
404 
405         reg |= ((uint32_t)LLWU_FILT_FILTF1_MASK << ((filterIndex - 1U) * 8U));
406 
407         base->FILT = reg;
408     }
409 
410 #endif
411 
412     return;
413 #else
414     volatile uint8_t *regBase;
415     uint8_t reg;
416 
417     switch (filterIndex)
418     {
419         case 1:
420             regBase = &base->FILT1;
421             break;
422 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
423         case 2:
424             regBase = &base->FILT2;
425             break;
426 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
427 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
428         case 3:
429             regBase = &base->FILT3;
430             break;
431 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
432 #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
433         case 4:
434             regBase = &base->FILT4;
435             break;
436 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
437         default:
438             regBase = NULL;
439             break;
440     }
441 
442     if (NULL != regBase)
443     {
444         reg = *regBase;
445         reg |= LLWU_FILT1_FILTF_MASK;
446         *regBase = reg;
447     }
448 #endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
449 }
450 #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
451 
452 #if (defined(FSL_FEATURE_LLWU_HAS_RESET_ENABLE) && FSL_FEATURE_LLWU_HAS_RESET_ENABLE)
453 /*!
454  * brief Sets the reset pin mode.
455  *
456  * This function determines how the reset pin is used as a low leakage mode exit source.
457  *
458  * param pinEnable       Enable reset the pin filter
459  * param pinFilterEnable Specify whether the pin filter is enabled in Low-Leakage power mode.
460  */
LLWU_SetResetPinMode(LLWU_Type * base,bool pinEnable,bool pinFilterEnable)461 void LLWU_SetResetPinMode(LLWU_Type *base, bool pinEnable, bool pinFilterEnable)
462 {
463     uint8_t reg;
464 
465     reg = base->RST;
466 
467     reg &= (uint8_t)(~(LLWU_RST_LLRSTE_MASK | LLWU_RST_RSTFILT_MASK));
468 
469     if (pinEnable)
470     {
471         reg |= LLWU_RST_LLRSTE_MASK;
472     }
473 
474     if (pinFilterEnable)
475     {
476         reg |= LLWU_RST_RSTFILT_MASK;
477     }
478 
479     base->RST = reg;
480 }
481 #endif /* FSL_FEATURE_LLWU_HAS_RESET_ENABLE */
482