1 /*
2  * Copyright 2020 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_cwt.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.cwt"
17 #endif
18 
19 /*******************************************************************************
20  * Prototypes
21  ******************************************************************************/
22 
23 /*******************************************************************************
24  * Code
25  ******************************************************************************/
26 
27 /*!
28  * brief Sets the default configuration of CWT
29  *
30  * This function initialize CWT config structure to default values.
31  *
32  * param conf CWT configuration structure
33  */
CWT_GetDefaultConfig(cwt_config_t * conf)34 void CWT_GetDefaultConfig(cwt_config_t *conf)
35 {
36     /* Default configuration after reset */
37     conf->lock       = (uint8_t)kCDOG_LockCtrl_Unlock;    /* Lock control */
38     conf->timeout    = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Timeout control */
39     conf->miscompare = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Miscompare control */
40     conf->sequence   = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Sequence control */
41     conf->control    = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Control */
42     conf->state      = (uint8_t)kCDOG_FaultCtrl_NoAction; /* State control */
43     conf->address    = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Address control */
44     conf->irq_pause  = (uint8_t)kCDOG_IrqPauseCtrl_Run;   /* IRQ pause control */
45     conf->debug_halt = (uint8_t)kCDOG_DebugHaltCtrl_Run;  /* Debug halt control */
46     return;
47 }
48 
49 /*!
50  * brief Sets secure counter and instruction timer values
51  *
52  * This function sets value in RELOAD and START registers for instruction timer.
53  *
54  * param base CWT peripheral base address
55  * param reload reload value
56  * param start start value
57  */
CWT_Start(CDOG_Type * base,uint32_t reload,uint32_t start)58 void CWT_Start(CDOG_Type *base, uint32_t reload, uint32_t start)
59 {
60     base->RELOAD = reload;
61     base->START  = start;
62 }
63 
64 /*!
65  * brief Stops secure counter and instruction timer
66  *
67  * This function stops instruction timer and secure counter.
68  * This also change state of CWT to IDLE.
69  *
70  * param base CWT peripheral base address
71  * param stop expected value which will be compared with value of secure counter
72  */
CWT_Stop(CDOG_Type * base,uint32_t stop)73 void CWT_Stop(CDOG_Type *base, uint32_t stop)
74 {
75     base->STOP = stop;
76 }
77 
78 /*!
79  * brief Sets secure counter and instruction timer values
80  *
81  * This function sets value in STOP, RELOAD and START registers
82  * for instruction timer and secure counter.
83  *
84  * param base CWT peripheral base address
85  * param stop expected value which will be compared with value of secure counter
86  * param reload reload value for instruction timer
87  * param start start value for secure timer
88  */
CWT_Set(CDOG_Type * base,uint32_t stop,uint32_t reload,uint32_t start)89 void CWT_Set(CDOG_Type *base, uint32_t stop, uint32_t reload, uint32_t start)
90 {
91     base->STOP   = stop;
92     base->RELOAD = reload;
93     base->START  = start;
94 }
95 
96 /*!
97  * brief Add value to secure counter
98  *
99  * This function add specified value to secure counter.
100  *
101  * param base CWT peripheral base address.
102  * param add Value to be added.
103  */
CWT_Add(CDOG_Type * base,uint32_t add)104 void CWT_Add(CDOG_Type *base, uint32_t add)
105 {
106     base->ADD = (secure_counter_t)add;
107 }
108 
109 /*!
110  * brief Add 1 to secure counter
111  *
112  * This function add 1 to secure counter.
113  *
114  * param base CWT peripheral base address.
115  * param add Value to be added.
116  */
CWT_Add1(CDOG_Type * base)117 void CWT_Add1(CDOG_Type *base)
118 {
119     base->ADD1 = (secure_counter_t)0x1U;
120 }
121 
122 /*!
123  * brief Add 16 to secure counter
124  *
125  * This function add 16 to secure counter.
126  *
127  * param base CWT peripheral base address.
128  * param add Value to be added.
129  */
CWT_Add16(CDOG_Type * base)130 void CWT_Add16(CDOG_Type *base)
131 {
132     base->ADD16 = (secure_counter_t)0x1U;
133 }
134 
135 /*!
136  * brief Add 256 to secure counter
137  *
138  * This function add 256 to secure counter.
139  *
140  * param base CWT peripheral base address.
141  * param add Value to be added.
142  */
CWT_Add256(CDOG_Type * base)143 void CWT_Add256(CDOG_Type *base)
144 {
145     base->ADD256 = (secure_counter_t)0x1U;
146 }
147 
148 /*!
149  * brief Substract value to secure counter
150  *
151  * This function substract specified value to secure counter.
152  *
153  * param base CWT peripheral base address.
154  * param sub Value to be substracted.
155  */
CWT_Sub(CDOG_Type * base,uint32_t sub)156 void CWT_Sub(CDOG_Type *base, uint32_t sub)
157 {
158     base->SUB = (secure_counter_t)sub;
159 }
160 
161 /*!
162  * brief Substract 1 from secure counter
163  *
164  * This function substract specified 1 from secure counter.
165  *
166  * param base CWT peripheral base address.
167  */
CWT_Sub1(CDOG_Type * base)168 void CWT_Sub1(CDOG_Type *base)
169 {
170     base->SUB1 = (secure_counter_t)0x1U;
171 }
172 
173 /*!
174  * brief Substract 16 from secure counter
175  *
176  * This function substract specified 16 from secure counter.
177  *
178  * param base CWT peripheral base address.
179  */
CWT_Sub16(CDOG_Type * base)180 void CWT_Sub16(CDOG_Type *base)
181 {
182     base->SUB16 = (secure_counter_t)0x1U;
183 }
184 
185 /*!
186  * brief Substract 256 from secure counter
187  *
188  * This function substract specified 256 from secure counter.
189  *
190  * param base CWT peripheral base address.
191  */
CWT_Sub256(CDOG_Type * base)192 void CWT_Sub256(CDOG_Type *base)
193 {
194     base->SUB256 = (secure_counter_t)0x1U;
195 }
196 
197 /*!
198  * brief Checks secure counter.
199  *
200  * This function compares stop value with secure counter value
201  * by writting to RELOAD refister.
202  *
203  * param base CWT peripheral base address
204  * param check expected (stop) value.
205  */
CWT_Check(CDOG_Type * base,uint32_t check)206 void CWT_Check(CDOG_Type *base, uint32_t check)
207 {
208     base->RESTART = check;
209 }
210 
211 /*!
212  * brief Set the CWT persistent word.
213  *
214  * param base CWT peripheral base address.
215  * param value The value to be written.
216  */
CWT_WritePersistent(CDOG_Type * base,uint32_t value)217 void CWT_WritePersistent(CDOG_Type *base, uint32_t value)
218 {
219     base->PERSISTENT = value;
220 }
221 
222 /*!
223  * brief Get the CWT persistent word.
224  *
225  * param base CWT peripheral base address.
226  * return The persistent word.
227  */
CWT_ReadPersistent(CDOG_Type * base)228 uint32_t CWT_ReadPersistent(CDOG_Type *base)
229 {
230     return base->PERSISTENT;
231 }
232 
233 /*!
234  * brief Initialize CWT
235  *
236  * This function initializes CWT block and setting.
237  *
238  * param base CWT peripheral base address
239  * param conf CWT configuration structure
240  * return Status of the init operation
241  */
CWT_Init(CDOG_Type * base,cwt_config_t * conf)242 status_t CWT_Init(CDOG_Type *base, cwt_config_t *conf)
243 {
244     /* Ungate clock to CWT engine and reset it */
245     CLOCK_EnableClock(kCLOCK_Cwt);
246     RESET_PeripheralReset(kCWT_RST_SHIFT_RSTn);
247 
248     if (base->CONTROL == 0x0U)
249     {
250         /* CWT is not in IDLE mode, which may be cause after SW reset. */
251         /* Writing to CONTROL register will trigger fault. */
252         return kStatus_Fail;
253     }
254 
255     /* Clear pending errors, otherwise the device will reset */
256     /* itself immediately after enable Code Watchdog */
257     if ((uint32_t)kCDOG_LockCtrl_Lock ==
258         ((base->CONTROL & CDOG_CONTROL_LOCK_CTRL_MASK) >> CDOG_CONTROL_LOCK_CTRL_SHIFT))
259 
260     {
261         CDOG->FLAGS = CDOG_FLAGS_TO_FLAG(1U) | CDOG_FLAGS_MISCOM_FLAG(1U) | CDOG_FLAGS_SEQ_FLAG(1U) |
262                       CDOG_FLAGS_CNT_FLAG(1U) | CDOG_FLAGS_STATE_FLAG(1U) | CDOG_FLAGS_ADDR_FLAG(1U) |
263                       CDOG_FLAGS_POR_FLAG(1U);
264     }
265     else
266     {
267         CDOG->FLAGS = CDOG_FLAGS_TO_FLAG(0U) | CDOG_FLAGS_MISCOM_FLAG(0U) | CDOG_FLAGS_SEQ_FLAG(0U) |
268                       CDOG_FLAGS_CNT_FLAG(0U) | CDOG_FLAGS_STATE_FLAG(0U) | CDOG_FLAGS_ADDR_FLAG(0U) |
269                       CDOG_FLAGS_POR_FLAG(0U);
270     }
271 
272     base->CONTROL =
273         CDOG_CONTROL_TIMEOUT_CTRL(conf->timeout) |       /* Action if the timeout event is triggered  */
274         CDOG_CONTROL_MISCOMPARE_CTRL(conf->miscompare) | /* Action if the miscompare error event is triggered  */
275         CDOG_CONTROL_SEQUENCE_CTRL(conf->sequence) |     /* Action if the sequence error event is triggered  */
276         CDOG_CONTROL_CONTROL_CTRL(conf->control) |       /* Action if the control error event is triggered  */
277         CDOG_CONTROL_STATE_CTRL(conf->state) |           /* Action if the state error event is triggered  */
278         CDOG_CONTROL_ADDRESS_CTRL(conf->address) |       /* Action if the address error event is triggered */
279         CDOG_CONTROL_IRQ_PAUSE(conf->irq_pause) |        /* Pause running during interrupts setup */
280         CDOG_CONTROL_DEBUG_HALT_CTRL(
281             conf->debug_halt) |             /* Halt CWT timer during debug so we have chance to debug code */
282         CDOG_CONTROL_LOCK_CTRL(conf->lock); /* Lock control register */
283 
284     NVIC_EnableIRQ(CodeWDG_IRQn);
285 
286     return kStatus_Success;
287 }
288 
289 /*!
290  * brief Deinitialize CWT
291  *
292  * This function stops CWT secure counter.
293  *
294  * param base CWT peripheral base address
295  */
CWT_Deinit(CDOG_Type * base)296 void CWT_Deinit(CDOG_Type *base)
297 {
298     NVIC_DisableIRQ(CodeWDG_IRQn);
299 
300     RESET_SetPeripheralReset(kCWT_RST_SHIFT_RSTn);
301 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
302     CLOCK_DisableClock(kCLOCK_Cwt);
303 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
304 }
305