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_wdog32.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.wdog32"
14 #endif
15 
16 #if defined(WDOG_RSTS)
17 #define WDOG_RESETS_ARRAY WDOG_RSTS
18 #endif
19 
20 /*
21  * $Coverage Justification Reference$
22  *
23  * $Justification wdog32_c_ref_1$
24  * Function not covered. Test unfeasible, the reset state is too short to catch.
25  *
26  */
27 
28 /*******************************************************************************
29  * Prototypes
30  ******************************************************************************/
31 #if defined(WDOG_RESETS_ARRAY)
32 /*!
33  * @brief Get instance number for WDOG32_ module.
34  *
35  * @param base WDOG32_ peripheral base address.
36  */
37 static uint32_t WDOG32_GetInstance(WDOG_Type *base);
38 #endif
39 
40 /*******************************************************************************
41  * Variables
42  ******************************************************************************/
43 #if defined(WDOG_RESETS_ARRAY)
44 static WDOG_Type *const s_wdogBases[] = WDOG_BASE_PTRS;
45 
46 /* Reset array */
47 static const reset_ip_name_t s_wdogResets[] = WDOG_RESETS_ARRAY;
48 #endif
49 /*******************************************************************************
50  * Code
51  ******************************************************************************/
52 #if defined(WDOG_RESETS_ARRAY)
WDOG32_GetInstance(WDOG_Type * base)53 static uint32_t WDOG32_GetInstance(WDOG_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_wdogBases); instance++)
59     {
60         if (s_wdogBases[instance] == base)
61         {
62             break;
63         }
64     }
65 
66     assert(instance < ARRAY_SIZE(s_wdogBases));
67 
68     return instance;
69 }
70 #endif
71 
WDOG32_ClearStatusFlags(WDOG_Type * base,uint32_t mask)72 void WDOG32_ClearStatusFlags(WDOG_Type *base, uint32_t mask)
73 {
74 
75     /* $Line Coverage Justification$ $ref wdog32_c_ref_1$. */
76     /* $Branch Coverage Justification$ $ref wdog32_c_ref_1$. */
77     if (0U != (mask & (uint32_t)kWDOG32_InterruptFlag))
78     {
79         base->CS |= WDOG_CS_FLG_MASK;
80     }
81 }
82 
83 /*!
84  * brief Initializes the WDOG32 configuration structure.
85  *
86  * This function initializes the WDOG32 configuration structure to default values. The default
87  * values are:
88  * code
89  *   wdog32Config->enableWdog32 = true;
90  *   wdog32Config->clockSource = kWDOG32_ClockSource1;
91  *   wdog32Config->prescaler = kWDOG32_ClockPrescalerDivide1;
92  *   wdog32Config->workMode.enableWait = true;
93  *   wdog32Config->workMode.enableStop = false;
94  *   wdog32Config->workMode.enableDebug = false;
95  *   wdog32Config->testMode = kWDOG32_TestModeDisabled;
96  *   wdog32Config->enableUpdate = true;
97  *   wdog32Config->enableInterrupt = false;
98  *   wdog32Config->enableWindowMode = false;
99  *   wdog32Config->windowValue = 0U;
100  *   wdog32Config->timeoutValue = 0xFFFFU;
101  * endcode
102  *
103  * param config Pointer to the WDOG32 configuration structure.
104  * see wdog32_config_t
105  */
WDOG32_GetDefaultConfig(wdog32_config_t * config)106 void WDOG32_GetDefaultConfig(wdog32_config_t *config)
107 {
108     assert(NULL != config);
109 
110     /* Initializes the configure structure to zero. */
111     (void)memset(config, 0, sizeof(*config));
112 
113     config->enableWdog32         = true;
114     config->clockSource          = kWDOG32_ClockSource1;
115     config->prescaler            = kWDOG32_ClockPrescalerDivide1;
116     config->workMode.enableWait  = true;
117     config->workMode.enableStop  = false;
118     config->workMode.enableDebug = false;
119     config->testMode             = kWDOG32_TestModeDisabled;
120     config->enableUpdate         = true;
121     config->enableInterrupt      = false;
122     config->enableWindowMode     = false;
123     config->windowValue          = 0U;
124     config->timeoutValue         = 0xFFFFU;
125 }
126 
WDOG32_Init(WDOG_Type * base,const wdog32_config_t * config)127 void WDOG32_Init(WDOG_Type *base, const wdog32_config_t *config)
128 {
129     assert(NULL != config);
130 
131     register uint32_t value                   = 0U;
132     uint32_t primaskValue                     = 0U;
133     register WDOG_Type *regBase               = base;
134     register const wdog32_config_t *regConfig = config;
135     uint32_t tempPrescaler                    = (uint32_t)regConfig->prescaler;
136 
137 #if defined(WDOG_RESETS_ARRAY)
138     RESET_ReleasePeripheralReset(s_wdogResets[WDOG32_GetInstance(base)]);
139 #endif
140 
141     value = WDOG_CS_EN((uint32_t)regConfig->enableWdog32) | WDOG_CS_CLK((uint32_t)regConfig->clockSource) |
142             WDOG_CS_INT((uint32_t)regConfig->enableInterrupt) | WDOG_CS_WIN((uint32_t)regConfig->enableWindowMode) |
143             WDOG_CS_UPDATE((uint32_t)regConfig->enableUpdate) | WDOG_CS_DBG((uint32_t)regConfig->workMode.enableDebug) |
144             WDOG_CS_STOP((uint32_t)regConfig->workMode.enableStop) |
145             WDOG_CS_WAIT((uint32_t)regConfig->workMode.enableWait) | WDOG_CS_PRES(tempPrescaler) |
146             WDOG_CS_CMD32EN(1UL) | WDOG_CS_TST((uint32_t)regConfig->testMode);
147 
148     /* Disable the global interrupts. Otherwise, an interrupt could effectively invalidate the unlock sequence
149      * and the WCT may expire. After the configuration finishes, re-enable the global interrupts. */
150     primaskValue = DisableGlobalIRQ();
151     WDOG32_Unlock(base);
152     regBase->WIN   = regConfig->windowValue;
153     regBase->TOVAL = regConfig->timeoutValue;
154     regBase->CS    = value;
155 #ifdef WDOG_CS_RCS_MASK
156     /* Waits until for new configuration to take effect. */
157     while (0U == ((base->CS) & WDOG_CS_RCS_MASK))
158     {
159         ;
160     }
161 #else
162     /* When switches clock sources during reconfiguration, the watchdog hardware holds the counter at
163        zero for 2.5 periods of the previous clock source and 2.5 periods of the new clock source
164        after the configuration time period (128 bus clocks) ends.
165        This delay ensures a smooth transition before restarting the counter with the new configuration. */
166     for (uint8_t timeDelay = 0U; timeDelay < 128U; timeDelay++)
167     {
168         (void)base->CNT;
169     }
170 #endif /* WDOG_CS_RCS_MASK */
171 
172     EnableGlobalIRQ(primaskValue);
173 }
174 
175 /*!
176  * brief De-initializes the WDOG32 module.
177  *
178  * This function shuts down the WDOG32.
179  * Ensure that the WDOG_CS.UPDATE is 1, which means that the register update is enabled.
180  *
181  * param base   WDOG32 peripheral base address.
182  */
WDOG32_Deinit(WDOG_Type * base)183 void WDOG32_Deinit(WDOG_Type *base)
184 {
185     uint32_t primaskValue = 0U;
186 
187     /* Disable the global interrupts */
188     primaskValue = DisableGlobalIRQ();
189     WDOG32_Unlock(base);
190     WDOG32_Disable(base);
191     EnableGlobalIRQ(primaskValue);
192 }
193 
194 /*!
195  * brief Unlocks the WDOG32 register written.
196  *
197  * This function unlocks the WDOG32 register written.
198  *
199  * Before starting the unlock sequence and following the configuration, disable the global interrupts.
200  * Otherwise, an interrupt could effectively invalidate the unlock sequence and the WCT may expire.
201  * After the configuration finishes, re-enable the global interrupts.
202  *
203  * param base WDOG32 peripheral base address
204  */
WDOG32_Unlock(WDOG_Type * base)205 void WDOG32_Unlock(WDOG_Type *base)
206 {
207     if (0U != ((base->CS) & WDOG_CS_CMD32EN_MASK))
208     {
209         base->CNT = WDOG_UPDATE_KEY;
210     }
211     else
212     {
213         base->CNT = WDOG_FIRST_WORD_OF_UNLOCK;
214         base->CNT = WDOG_SECOND_WORD_OF_UNLOCK;
215     }
216 #ifdef WDOG_CS_ULK_MASK
217     /* Waited until for registers to be unlocked. */
218     while (0U == ((base->CS) & WDOG_CS_ULK_MASK))
219     {
220         ;
221     }
222 #endif /* WDOG_CS_ULK_MASK */
223 }
224 
225 /*!
226  * brief Enables the WDOG32 module.
227  *
228  * This function writes a value into the WDOG_CS register to enable the WDOG32.
229  * The WDOG_CS register is a write-once register. Please check the enableUpdate is set to true for calling WDOG32_Init
230  * to do wdog initialize, before call the re-configuration APIs, ensure that the WCT window is still open and
231  * this register has not been written in this WCT while the function is called.
232  *
233  * param base WDOG32 peripheral base address.
234  */
WDOG32_Enable(WDOG_Type * base)235 void WDOG32_Enable(WDOG_Type *base)
236 {
237     base->CS |= WDOG_CS_EN_MASK;
238 }
239 
240 /*!
241  * brief Disables the WDOG32 module.
242  *
243  * This function writes a value into the WDOG_CS register to disable the WDOG32.
244  * The WDOG_CS register is a write-once register. Please check the enableUpdate is set to true for calling WDOG32_Init
245  * to do wdog initialize, before call the re-configuration APIs, ensure that the WCT window is still open and
246  * this register has not been written in this WCT while the function is called.
247  *
248  * param base WDOG32 peripheral base address
249  */
WDOG32_Disable(WDOG_Type * base)250 void WDOG32_Disable(WDOG_Type *base)
251 {
252     base->CS &= ~WDOG_CS_EN_MASK;
253 }
254 
255 /*!
256  * brief Enables the WDOG32 interrupt.
257  *
258  * This function writes a value into the WDOG_CS register to enable the WDOG32 interrupt.
259  * The WDOG_CS register is a write-once register. Please check the enableUpdate is set to true for calling WDOG32_Init
260  * to do wdog initialize, before call the re-configuration APIs, ensure that the WCT window is still open and
261  * this register has not been written in this WCT while the function is called.
262  *
263  * param base WDOG32 peripheral base address.
264  * param mask The interrupts to enable.
265  *        The parameter can be a combination of the following source if defined:
266  *        arg kWDOG32_InterruptEnable
267  */
WDOG32_EnableInterrupts(WDOG_Type * base,uint32_t mask)268 void WDOG32_EnableInterrupts(WDOG_Type *base, uint32_t mask)
269 {
270     base->CS |= mask;
271 }
272 
273 /*!
274  * brief Disables the WDOG32 interrupt.
275  *
276  * This function writes a value into the WDOG_CS register to disable the WDOG32 interrupt.
277  * The WDOG_CS register is a write-once register. Please check the enableUpdate is set to true for calling WDOG32_Init
278  * to do wdog initialize, before call the re-configuration APIs, ensure that the WCT window is still open and
279  * this register has not been written in this WCT while the function is called.
280  *
281  * param base WDOG32 peripheral base address.
282  * param mask The interrupts to disabled.
283  *        The parameter can be a combination of the following source if defined:
284  *        arg kWDOG32_InterruptEnable
285  */
WDOG32_DisableInterrupts(WDOG_Type * base,uint32_t mask)286 void WDOG32_DisableInterrupts(WDOG_Type *base, uint32_t mask)
287 {
288     base->CS &= ~mask;
289 }
290 
291 /*!
292  * brief Sets the WDOG32 timeout value.
293  *
294  * This function writes a timeout value into the WDOG_TOVAL register.
295  * The WDOG_TOVAL register is a write-once register. To ensure the reconfiguration fits the timing of WCT, unlock
296  * function will be called in the function.
297  *
298  * param base WDOG32 peripheral base address
299  * param timeoutCount WDOG32 timeout value, count of WDOG32 clock ticks.
300  */
WDOG32_SetTimeoutValue(WDOG_Type * base,uint16_t timeoutCount)301 void WDOG32_SetTimeoutValue(WDOG_Type *base, uint16_t timeoutCount)
302 {
303     base->TOVAL = timeoutCount;
304 }
305 
306 /*!
307  * brief Sets the WDOG32 window value.
308  *
309  * This function writes a window value into the WDOG_WIN register.
310  * The WDOG_WIN register is a write-once register. Ensure that the WCT window is still open and
311  * this register has not been written in this WCT while the function is called.
312  *
313  * param base WDOG32 peripheral base address.
314  * param windowValue WDOG32 window value.
315  */
WDOG32_SetWindowValue(WDOG_Type * base,uint16_t windowValue)316 void WDOG32_SetWindowValue(WDOG_Type *base, uint16_t windowValue)
317 {
318     base->WIN = windowValue;
319 }
320