1 /*
2  * Copyright 2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_waketimer.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.waketimer"
17 #endif
18 
19 /*******************************************************************************
20  * Prototypes
21  ******************************************************************************/
22 /*!
23  * brief Gets the instance from the base address
24  *
25  * param base WAKETIMER peripheral base address
26  *
27  * return The WAKETIMER instance
28  */
29 static uint32_t WAKETIMER_GetInstance(WAKETIMER_Type *base);
30 
31 /*!
32  * brief WAKETIMER generic IRQ handle function.
33  *
34  * param index WAKETIMER peripheral instance index.
35  */
36 static void WAKETIMER_GenericIRQHandler(WAKETIMER_Type *base, waketimer_callback_t callback);
37 
38 /*******************************************************************************
39  * Variables
40  ******************************************************************************/
41 /* Array of WAKETIMER peripheral base address. */
42 static WAKETIMER_Type *const s_waketimerBases[] = WAKETIMER_BASE_PTRS;
43 /* Array of WAKETIMER ISR. */
44 static waketimer_callback_t s_waketimerCallback[sizeof(s_waketimerBases) / sizeof(s_waketimerBases[0])];
45 /* Array of WAKETIMER IRQ number. */
46 static const IRQn_Type s_waketimerIRQ[] = WAKETIMER_IRQS;
47 
48 /*******************************************************************************
49  * Code
50  ******************************************************************************/
51 
52 /* brief Function for getting the instance number of Waketimer. */
WAKETIMER_GetInstance(WAKETIMER_Type * base)53 static uint32_t WAKETIMER_GetInstance(WAKETIMER_Type *base)
54 {
55     uint32_t instance;
56 
57     /* Find the instance index from base address mappings. */
58     for (instance = 0; instance < ARRAY_SIZE(s_waketimerBases); instance++)
59     {
60         if (s_waketimerBases[instance] == base)
61         {
62             break;
63         }
64     }
65 
66     assert(instance < ARRAY_SIZE(s_waketimerBases));
67 
68     return instance;
69 }
70 
71 /*!
72  * brief Initializes an WAKETIMER.
73  * param base WAKETIMER peripheral base address.
74  */
WAKETIMER_Init(WAKETIMER_Type * base,const waketimer_config_t * config)75 void WAKETIMER_Init(WAKETIMER_Type *base, const waketimer_config_t *config)
76 {
77     assert(NULL != base);
78 
79     uint32_t index = WAKETIMER_GetInstance(base);
80 
81     /* Halt timer */
82     base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_CLR_WAKE_TIMER_MASK;
83 
84     /* Set OSC divide */
85     if (config->enableOSCDivide)
86     {
87         base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_OSC_DIV_ENA_MASK;
88     }
89     else
90     {
91         base->WAKE_TIMER_CTRL &= ~WAKETIMER_WAKE_TIMER_CTRL_OSC_DIV_ENA_MASK;
92     }
93 
94     /* Set callback */
95     s_waketimerCallback[index] = config->callback;
96 
97     /* Set interrupt */
98     if (config->enableInterrupt)
99     {
100         base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_INTR_EN_MASK;
101         (void)EnableIRQ(s_waketimerIRQ[index]);
102     }
103     else
104     {
105         base->WAKE_TIMER_CTRL &= ~WAKETIMER_WAKE_TIMER_CTRL_INTR_EN_MASK;
106         (void)DisableIRQ(s_waketimerIRQ[index]);
107     }
108 }
109 
110 /*!
111  * brief Deinitializes a WAKETIMER instance.
112  *
113  * This function deinitializes the WAKETIMER.
114  *
115  * param base WAKETIMER peripheral base address.
116  */
WAKETIMER_Deinit(WAKETIMER_Type * base)117 void WAKETIMER_Deinit(WAKETIMER_Type *base)
118 {
119     assert(NULL != base);
120 
121     uint32_t index = WAKETIMER_GetInstance(base);
122 
123     /* Disable IRQ at NVIC Level */
124     (void)DisableIRQ(s_waketimerIRQ[index]);
125 }
126 
127 /*!
128  * brief  Fills in the WAKETIMER configuration structure with the default settings.
129  *
130  * The default values are:
131  * code
132  *  config->enableInterrupt = true;
133  *  config->enableOSCDivide = true;
134  *  config->callback        = NULL;
135  * endcode
136  * param config Pointer to the user configuration structure.
137  */
WAKETIMER_GetDefaultConfig(waketimer_config_t * config)138 void WAKETIMER_GetDefaultConfig(waketimer_config_t *config)
139 {
140     config->enableInterrupt = true;
141     config->enableOSCDivide = true;
142     config->callback        = NULL;
143 }
144 
145 /*!
146  * brief Enables the selected WAKETIMER interrupts.
147  *
148  * param base WAKETIMER peripheral base address
149  * param mask Mask value for interrupt events. See to #_waketimer_interrupt_enable
150  */
WAKETIMER_EnableInterrupts(WAKETIMER_Type * base,uint32_t mask)151 void WAKETIMER_EnableInterrupts(WAKETIMER_Type *base, uint32_t mask)
152 {
153     assert(NULL != base);
154 
155     if (0U != (mask & (uint32_t)kWAKETIMER_WakeInterruptEnable))
156     {
157         base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_INTR_EN_MASK;
158     }
159 }
160 
161 /*!
162  * brief Disable the selected WAKETIMER interrupts.
163  *
164  * param base WAKETIMER peripheral base address
165  * param mask Mask value for interrupt events. See to #_waketimer_interrupt_enable
166  */
WAKETIMER_DisableInterrupts(WAKETIMER_Type * base,uint32_t mask)167 void WAKETIMER_DisableInterrupts(WAKETIMER_Type *base, uint32_t mask)
168 {
169     assert(NULL != base);
170 
171     if (0U != (mask & (uint32_t)kWAKETIMER_WakeInterruptEnable))
172     {
173         base->WAKE_TIMER_CTRL &= ~WAKETIMER_WAKE_TIMER_CTRL_INTR_EN_MASK;
174     }
175 }
176 
177 /*!
178  * brief Clear Status Interrupt Flag.
179  *
180  * This clears intrrupt status flag.
181  * Currently, only match interrupt flag can be cleared.
182  *
183  * param base WAKETIMER peripheral base address.
184  * param mask Mask value for flags to be cleared. See to #_waketimer_status_flags.
185  * return none
186  */
WAKETIMER_ClearStatusFlags(WAKETIMER_Type * base,uint32_t mask)187 void WAKETIMER_ClearStatusFlags(WAKETIMER_Type *base, uint32_t mask)
188 {
189     if (0U != (mask & (uint32_t)kWAKETIMER_WakeFlag))
190     {
191         base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_WAKE_FLAG_MASK;
192     }
193 }
194 
195 /*!
196  * brief Receive noticification when waketime countdown.
197  *
198  * If the interrupt for the waketime countdown is enabled, then a callback can be registered
199  * which will be invoked when the event is triggered
200  *
201  * param base     WAKETIMER peripheral base address
202  * param callback Function to invoke when the event is triggered
203  */
WAKETIMER_SetCallback(WAKETIMER_Type * base,waketimer_callback_t callback)204 void WAKETIMER_SetCallback(WAKETIMER_Type *base, waketimer_callback_t callback)
205 {
206     assert(NULL != base);
207 
208     uint32_t index             = WAKETIMER_GetInstance(base);
209     s_waketimerCallback[index] = callback;
210 }
211 
212 /*!
213  * brief Get current timer count value from WAKETIMER.
214  *
215  * This function will get a decimal timer count value.
216  * The RAW value of timer count is gray code format, will be translated to decimal data internally.
217  *
218  * param base   WAKETIMER peripheral base address.
219  * return Value of WAKETIMER which will formated to decimal value.
220  */
WAKETIMER_GetCurrentTimerValue(WAKETIMER_Type * base)221 uint32_t WAKETIMER_GetCurrentTimerValue(WAKETIMER_Type *base)
222 {
223     uint32_t value1 = 0;
224     uint32_t value2 = 0;
225 
226     do
227     {
228         value1 = base->WAKE_TIMER_CNT;
229         value2 = base->WAKE_TIMER_CNT;
230     } while (value1 != value2);
231 
232     return value1;
233 }
234 
WAKETIMER_GenericIRQHandler(WAKETIMER_Type * base,waketimer_callback_t callback)235 static void WAKETIMER_GenericIRQHandler(WAKETIMER_Type *base, waketimer_callback_t callback)
236 {
237     /* Clear interrupt flag. */
238     WAKETIMER_ClearStatusFlags(base, (uint32_t)kWAKETIMER_WakeFlag);
239 
240     if (callback != NULL)
241     {
242         callback();
243     }
244 }
245 
246 #if defined(WAKETIMER0)
247 void WAKETIMER0_DriverIRQHandler(void);
WAKETIMER0_DriverIRQHandler(void)248 void WAKETIMER0_DriverIRQHandler(void)
249 {
250     WAKETIMER_GenericIRQHandler(WAKETIMER0, s_waketimerCallback[0]);
251     SDK_ISR_EXIT_BARRIER;
252 }
253 #endif
254