1 /*
2 * Copyright 2020-2022 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_cdog.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.cdog"
17 #endif
18
19 /* Reset CONTROL mask */
20 #define RESERVED_CTRL_MASK 0x800u
21
22 #if defined(CDOG_IRQS)
23 /* Array of IRQs */
24 static const IRQn_Type s_CdogIrqs[] = CDOG_IRQS;
25 #endif /* CDOG_IRQS */
26
27 /*******************************************************************************
28 * Prototypes
29 ******************************************************************************/
30
31 /*******************************************************************************
32 * Code
33 ******************************************************************************/
34 #if defined(CDOG)
35 /*!
36 * Weak implementation of CDOG IRQ, should be re-defined by user when using CDOG IRQ
37 */
CDOG_DriverIRQHandler(void)38 __WEAK void CDOG_DriverIRQHandler(void)
39 {
40 /* NVIC_DisableIRQ(CDOG_IRQn);
41 * CDOG_Stop(CDOG, s_start);
42 * CDOG->FLAGS = 0x0U;
43 * CDOG_Start(CDOG, 0xFFFFFFU, s_start);
44 * NVIC_EnableIRQ(CDOG_IRQn);
45 */
46 }
47 #endif
48
49 #if defined(CDOG0)
50 /*!
51 * Weak implementation of CDOG0 IRQ, should be re-defined by user when using CDOG IRQ
52 */
CDOG0_DriverIRQHandler(void)53 __WEAK void CDOG0_DriverIRQHandler(void)
54 {
55 /* NVIC_DisableIRQ(CDOG0_IRQn);
56 * CDOG_Stop(CDOG0, s_start);
57 * CDOG0->FLAGS = 0x0U;
58 * CDOG_Start(CDOG0, 0xFFFFFFU, s_start);
59 * NVIC_EnableIRQ(CDOG0_IRQn);
60 */
61 }
62 #endif
63
64 #if defined(CDOG1)
65 /*!
66 * Weak implementation of CDOG1 IRQ, should be re-defined by user when using CDOG IRQ
67 */
CDOG1_DriverIRQHandler(void)68 __WEAK void CDOG1_DriverIRQHandler(void)
69 {
70 /* NVIC_DisableIRQ(CDOG1_IRQn);
71 * CDOG_Stop(CDOG1, s_start);
72 * CDOG1->FLAGS = 0x0U;
73 * CDOG_Start(CDOG1, 0xFFFFFFU, s_start);
74 * NVIC_EnableIRQ(CDOG1_IRQn);
75 */
76 }
77 #endif
78
79 /*!
80 * brief Sets the default configuration of CDOG
81 *
82 * This function initialize CDOG config structure to default values.
83 *
84 * param conf CDOG configuration structure
85 */
CDOG_GetDefaultConfig(cdog_config_t * conf)86 void CDOG_GetDefaultConfig(cdog_config_t *conf)
87 {
88 /* Default configuration after reset */
89 conf->lock = (uint8_t)kCDOG_LockCtrl_Unlock; /* Lock control */
90 conf->timeout = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Timeout control */
91 conf->miscompare = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Miscompare control */
92 conf->sequence = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Sequence control */
93 conf->state = (uint8_t)kCDOG_FaultCtrl_NoAction; /* State control */
94 conf->address = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Address control */
95 conf->irq_pause = (uint8_t)kCDOG_IrqPauseCtrl_Run; /* IRQ pause control */
96 conf->debug_halt = (uint8_t)kCDOG_DebugHaltCtrl_Run; /* Debug halt control */
97 return;
98 }
99
100 /*!
101 * brief Sets secure counter and instruction timer values
102 *
103 * This function sets value in RELOAD and START registers for instruction timer.
104 *
105 * param base CDOG peripheral base address
106 * param reload reload value
107 * param start start value
108 */
CDOG_Start(CDOG_Type * base,uint32_t reload,uint32_t start)109 void CDOG_Start(CDOG_Type *base, uint32_t reload, uint32_t start)
110 {
111 base->RELOAD = reload;
112 base->START = start;
113 }
114
115 /*!
116 * brief Stops secure counter and instruction timer
117 *
118 * This function stops instruction timer and secure counter.
119 * This also change state of CDOG to IDLE.
120 *
121 * param base CDOG peripheral base address
122 * param stop expected value which will be compared with value of secure counter
123 */
CDOG_Stop(CDOG_Type * base,uint32_t stop)124 void CDOG_Stop(CDOG_Type *base, uint32_t stop)
125 {
126 base->STOP = stop;
127 }
128
129 /*!
130 * brief Sets secure counter and instruction timer values
131 *
132 * This function sets value in STOP, RELOAD and START registers
133 * for instruction timer and secure counter.
134 *
135 * param base CDOG peripheral base address
136 * param stop expected value which will be compared with value of secure counter
137 * param reload reload value for instruction timer
138 * param start start value for secure timer
139 */
CDOG_Set(CDOG_Type * base,uint32_t stop,uint32_t reload,uint32_t start)140 void CDOG_Set(CDOG_Type *base, uint32_t stop, uint32_t reload, uint32_t start)
141 {
142 base->STOP = stop;
143 base->RELOAD = reload;
144 base->START = start;
145 }
146
147 /*!
148 * brief Add value to secure counter
149 *
150 * This function add specified value to secure counter.
151 *
152 * param base CDOG peripheral base address.
153 * param add Value to be added.
154 */
CDOG_Add(CDOG_Type * base,uint32_t add)155 void CDOG_Add(CDOG_Type *base, uint32_t add)
156 {
157 base->ADD = (secure_counter_t)add;
158 }
159
160 /*!
161 * brief Add 1 to secure counter
162 *
163 * This function add 1 to secure counter.
164 *
165 * param base CDOG peripheral base address.
166 * param add Value to be added.
167 */
CDOG_Add1(CDOG_Type * base)168 void CDOG_Add1(CDOG_Type *base)
169 {
170 base->ADD1 = (secure_counter_t)0x1U;
171 }
172
173 /*!
174 * brief Add 16 to secure counter
175 *
176 * This function add 16 to secure counter.
177 *
178 * param base CDOG peripheral base address.
179 * param add Value to be added.
180 */
CDOG_Add16(CDOG_Type * base)181 void CDOG_Add16(CDOG_Type *base)
182 {
183 base->ADD16 = (secure_counter_t)0x1U;
184 }
185
186 /*!
187 * brief Add 256 to secure counter
188 *
189 * This function add 256 to secure counter.
190 *
191 * param base CDOG peripheral base address.
192 * param add Value to be added.
193 */
CDOG_Add256(CDOG_Type * base)194 void CDOG_Add256(CDOG_Type *base)
195 {
196 base->ADD256 = (secure_counter_t)0x1U;
197 }
198
199 /*!
200 * brief Substract value to secure counter
201 *
202 * This function substract specified value to secure counter.
203 *
204 * param base CDOG peripheral base address.
205 * param sub Value to be substracted.
206 */
CDOG_Sub(CDOG_Type * base,uint32_t sub)207 void CDOG_Sub(CDOG_Type *base, uint32_t sub)
208 {
209 base->SUB = (secure_counter_t)sub;
210 }
211
212 /*!
213 * brief Substract 1 from secure counter
214 *
215 * This function substract specified 1 from secure counter.
216 *
217 * param base CDOG peripheral base address.
218 */
CDOG_Sub1(CDOG_Type * base)219 void CDOG_Sub1(CDOG_Type *base)
220 {
221 base->SUB1 = (secure_counter_t)0x1U;
222 }
223
224 /*!
225 * brief Substract 16 from secure counter
226 *
227 * This function substract specified 16 from secure counter.
228 *
229 * param base CDOG peripheral base address.
230 */
CDOG_Sub16(CDOG_Type * base)231 void CDOG_Sub16(CDOG_Type *base)
232 {
233 base->SUB16 = (secure_counter_t)0x1U;
234 }
235
236 /*!
237 * brief Substract 256 from secure counter
238 *
239 * This function substract specified 256 from secure counter.
240 *
241 * param base CDOG peripheral base address.
242 */
CDOG_Sub256(CDOG_Type * base)243 void CDOG_Sub256(CDOG_Type *base)
244 {
245 base->SUB256 = (secure_counter_t)0x1U;
246 }
247
248 /*!
249 * brief Checks secure counter.
250 *
251 * This function compares stop value with secure counter value
252 * by writting to RELOAD refister.
253 *
254 * param base CDOG peripheral base address
255 * param check expected (stop) value.
256 */
CDOG_Check(CDOG_Type * base,uint32_t check)257 void CDOG_Check(CDOG_Type *base, uint32_t check)
258 {
259 base->RESTART = check;
260 }
261
262 /*!
263 * brief Set the CDOG persistent word.
264 *
265 * param base CDOG peripheral base address.
266 * param value The value to be written.
267 */
CDOG_WritePersistent(CDOG_Type * base,uint32_t value)268 void CDOG_WritePersistent(CDOG_Type *base, uint32_t value)
269 {
270 base->PERSISTENT = value;
271 }
272
273 /*!
274 * brief Get the CDOG persistent word.
275 *
276 * param base CDOG peripheral base address.
277 * return The persistent word.
278 */
CDOG_ReadPersistent(CDOG_Type * base)279 uint32_t CDOG_ReadPersistent(CDOG_Type *base)
280 {
281 return base->PERSISTENT;
282 }
283
284 /*!
285 * brief Initialize CDOG
286 *
287 * This function initializes CDOG setting and enable all interrupts.
288 *
289 * param base CDOG peripheral base address
290 * param conf CDOG configuration structure
291 * return Status of the init operation
292 */
CDOG_Init(CDOG_Type * base,cdog_config_t * conf)293 status_t CDOG_Init(CDOG_Type *base, cdog_config_t *conf)
294 {
295 /* Ungate clock to CDOG engine and reset it */
296 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
297 #ifdef CDOG_CLOCKS
298 CLOCK_EnableClock(kCLOCK_Cdog);
299 #endif /* CDOG_CLOCKS */
300 #endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
301
302 #if !(defined(FSL_FEATURE_CDOG_HAS_NO_RESET) && FSL_FEATURE_CDOG_HAS_NO_RESET)
303 RESET_PeripheralReset(kCDOG_RST_SHIFT_RSTn);
304 #endif /* !FSL_FEATURE_CDOG_HAS_NO_RESET */
305
306 if (base->CONTROL == 0x0U)
307 {
308 /* CDOG is not in IDLE mode, which may be cause after SW reset. */
309 /* Writing to CONTROL register will trigger fault. */
310 return kStatus_Fail;
311 }
312
313 /* Clear pending errors, otherwise the device will reset */
314 /* itself immediately after enable Code Watchdog */
315 if ((uint32_t)kCDOG_LockCtrl_Lock ==
316 ((base->CONTROL & CDOG_CONTROL_LOCK_CTRL_MASK) >> CDOG_CONTROL_LOCK_CTRL_SHIFT))
317
318 {
319 base->FLAGS = CDOG_FLAGS_TO_FLAG(1U) | CDOG_FLAGS_MISCOM_FLAG(1U) | CDOG_FLAGS_SEQ_FLAG(1U) |
320 CDOG_FLAGS_CNT_FLAG(1U) | CDOG_FLAGS_STATE_FLAG(1U) | CDOG_FLAGS_ADDR_FLAG(1U) |
321 CDOG_FLAGS_POR_FLAG(1U);
322 }
323 else
324 {
325 base->FLAGS = CDOG_FLAGS_TO_FLAG(0U) | CDOG_FLAGS_MISCOM_FLAG(0U) | CDOG_FLAGS_SEQ_FLAG(0U) |
326 CDOG_FLAGS_CNT_FLAG(0U) | CDOG_FLAGS_STATE_FLAG(0U) | CDOG_FLAGS_ADDR_FLAG(0U) |
327 CDOG_FLAGS_POR_FLAG(0U);
328 }
329
330 base->CONTROL =
331 CDOG_CONTROL_TIMEOUT_CTRL(conf->timeout) | /* Action if the timeout event is triggered */
332 CDOG_CONTROL_MISCOMPARE_CTRL(conf->miscompare) | /* Action if the miscompare error event is triggered */
333 CDOG_CONTROL_SEQUENCE_CTRL(conf->sequence) | /* Action if the sequence error event is triggered */
334 CDOG_CONTROL_STATE_CTRL(conf->state) | /* Action if the state error event is triggered */
335 CDOG_CONTROL_ADDRESS_CTRL(conf->address) | /* Action if the address error event is triggered */
336 CDOG_CONTROL_IRQ_PAUSE(conf->irq_pause) | /* Pause running during interrupts setup */
337 CDOG_CONTROL_DEBUG_HALT_CTRL(conf->debug_halt) | /* Halt CDOG timer during debug */
338 CDOG_CONTROL_LOCK_CTRL(conf->lock) | RESERVED_CTRL_MASK; /* Lock control register, RESERVED */
339
340 #if defined(CDOG_IRQS)
341 /* Enable peripheral IRQs, if defined in array */
342 for (uint32_t i = 0; i < ARRAY_SIZE(s_CdogIrqs); i++)
343 {
344 NVIC_EnableIRQ(s_CdogIrqs[i]);
345 }
346 #endif /* CDOG_IRQS */
347
348 return kStatus_Success;
349 }
350
351 /*!
352 * brief Deinitialize CDOG
353 *
354 * This function stops CDOG secure counter.
355 *
356 * param base CDOG peripheral base address
357 */
CDOG_Deinit(CDOG_Type * base)358 void CDOG_Deinit(CDOG_Type *base)
359 {
360 #if defined(CDOG_IRQS)
361 /* Enable peripheral IRQs, if defined in array */
362 for (uint32_t i = 0; i < ARRAY_SIZE(s_CdogIrqs); i++)
363 {
364 NVIC_DisableIRQ(s_CdogIrqs[i]);
365 }
366 #endif /* CDOG_IRQS */
367
368 #if !(defined(FSL_FEATURE_CDOG_HAS_NO_RESET) && FSL_FEATURE_CDOG_HAS_NO_RESET)
369 RESET_SetPeripheralReset(kCDOG_RST_SHIFT_RSTn);
370 #endif /* !FSL_FEATURE_CDOG_HAS_NO_RESET */
371
372 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
373 #ifdef CDOG_CLOCKS
374 CLOCK_DisableClock(kCLOCK_Cdog);
375 #endif /* CDOG_CLOCKS */
376 #endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
377 }
378