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